Decorator Basics

Carson West

Chaining Decorators

Decorator Basics Decorators are a powerful and expressive feature in Python that allows you to modify or enhance functions and methods in a clean and readable way. They use the @ symbol followed by the decorator function name, placed above the function definition.

Basic Syntax:

def my_decorator(func):
    def wrapper():
        print("Something is happening before the function is called.")
        func()
        print("Something is happening after the function is called.")
    return wrapper

@my_decorator
def say_hello():
    print("Hello!")

say_hello()

This will print:

Something is happening before the function is called.
Hello!
Something is happening after the function is called.

How it works:

The @my_decorator syntax is syntactic sugar for:

say_hello = my_decorator(say_hello)

my_decorator takes the function say_hello as input, and returns a new function (wrapper) which wraps the original functionality with additional code. The wrapper function then becomes the new say_hello.

Decorators with Arguments: Decorators can also accept arguments. This requires a bit more complexity:

def repeat(num_times):
    def decorator_repeat(func):
        def wrapper(*args, **kwargs):
            for _ in range(num_times):
                result = func(*args, **kwargs)
            return result
        return wrapper
    return decorator_repeat

@repeat(num_times=3)
def greet(name):
    print(f"Hello, {name}!")

greet("World")

This uses a closure to handle the num_times argument. The outer function repeat returns the actual decorator (decorator_repeat).

Decorator Advanced Usage (This will be a separate note)

Closures in Python (This will be a separate note)

Example Use Cases:

Note: When using decorators with methods (functions within a class), you need to use functools.wraps to preserve metadata like the function’s name and docstring. This is crucial for debugging and introspection. See Decorator Gotchas

Decorator Gotchas (This will be a separate note)