Introduction to Python Decorators

Decorators are one of Python's most powerful features, allowing you to modify or enhance functions and classes without changing their source code. They are essentially functions that take another function as an argument and extend its behavior.

How Decorators Work

At their core, decorators are syntactic sugar for function composition. When you use the @decorator syntax, Python automatically passes the decorated function to the decorator function and replaces the original function with the result.

Simple Function Decorator Example

def timer_decorator(func):
    def wrapper(*args, **kwargs):
        start = time.time()
        result = func(*args, **kwargs)
        end = time.time()
        print(f"{func.__name__} took {end-start:.4f} seconds")
        return result
    return wrapper

@timer_decorator
def slow_function():
    time.sleep(2)
    return "Done"

Advanced Decorator Patterns

Decorator Type Use Case Complexity
Function Decorators Logging, timing, caching Beginner
Class Decorators Singleton, registry patterns Intermediate
Decorators with Arguments Configurable behavior Advanced
Class-based Decorators Stateful decorations Advanced

Real-world Applications

Decorators are extensively used in web frameworks like Flask and Django for route handling, in testing frameworks for setup/teardown, and in caching libraries like functools.lru_cache.