logo

Decorators That Take Parameters

Sometimes you want to configure a decorator:

@repeat(3)
def say_hello():
    print("Hello!")

This requires an extra layer - a function that returns a decorator:

def repeat(times):
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            for _ in range(times):
                func(*args, **kwargs)
        return wrapper
    return decorator

Think of it as: repeat(3) returns a decorator, which is then applied to say_hello.

Three levels:

  1. Outer function receives the parameter (times)
  2. Middle function receives the function to decorate (func)
  3. Inner function is the actual wrapper

This pattern is common in frameworks - Flask's @app.route("/path") works this way.

I explain parameterized decorators in my Python Decorators course.