Advanced Python: Decorators, Context Managers, and Metaclasses

Beyond the Basics

Python's simplicity is deceptive. Beneath its clean syntax lie powerful abstractions that, when mastered, enable elegant solutions to complex problems.

Decorators

Decorators modify or extend function behavior without changing the function itself. They're essential for cross-cutting concerns like logging, authentication, and caching.

import functools
import time

def timing(func):
    """Measure execution time of a function."""
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        start = time.perf_counter()
        result = func(*args, **kwargs)
        elapsed = time.perf_counter() - start
        print(f"{func.__name__} took {elapsed:.4f}s")
        return result
    return wrapper

def retry(max_attempts=3, delay=1):
    """Retry a function on failure."""
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            for attempt in range(max_attempts):
                try:
                    return func(*args, **kwargs)
                except Exception as e:
                    if attempt == max_attempts - 1:
                        raise
                    time.sleep(delay)
        return wrapper
    return decorator

@timing
@retry(max_attempts=3)
def fetch_data(url):
    import requests
    return requests.get(url).json()

Context Managers

Context managers ensure proper resource acquisition and release, making your code both safer and more readable.

from contextlib import contextmanager

@contextmanager
def database_transaction(connection):
    """Manage database transactions with automatic rollback on error."""
    cursor = connection.cursor()
    try:
        yield cursor
        connection.commit()
    except Exception:
        connection.rollback()
        raise
    finally:
        cursor.close()

# Usage
with database_transaction(conn) as cursor:
    cursor.execute("INSERT INTO users (name) VALUES (%s)", ("Alice",))
    cursor.execute("UPDATE stats SET user_count = user_count + 1")

Metaclasses

Metaclasses control class creation itself. While rarely needed, they're powerful for building frameworks, ORMs, and validation systems — Django's model system is built on metaclasses.

When to Use Each

Use decorators for modifying function behavior. Use context managers for resource management. Use metaclasses only when decorators and class inheritance aren't sufficient — which is rare in application code.

Next Building REST APIs with Django REST Framework

💬 Comments (0)

No comments yet. Be the first to share your thoughts!

Leave a Comment

Want to receive reply notifications? Login or Sign up to get notified when someone replies to your comment!

Your comment will be reviewed before it appears publicly.