Python > Advanced Topics and Specializations > Meta-programming > Decorators
Decorator with Arguments (Decorator Factory)
This example demonstrates a decorator factory. This is a decorator that takes arguments and returns a decorator. This is useful when you need to configure the behavior of your decorator.
Concepts Behind Decorator Factories
A decorator factory is a function that returns a decorator. This allows you to pass arguments to the decorator. This is useful when you need to configure the behavior of your decorator based on some parameters. The decorator factory pattern is used to create parameterized decorators.
The Logging Decorator Factory
The log function is our decorator factory. It takes a message as input. Inside log, we define a decorator function that takes the original function func as input. Inside decorator, we define a wrapper function that will be executed when the decorated function is called. The wrapper prints a log message before and after calling the original function func. Finally, the decorator function returns the wrapper function, and the log function returns the decorator. The @log('DEBUG') syntax above add is equivalent to writing add = log('DEBUG')(add).
import functools
def log(message):
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
print(f'{message}: Calling {func.__name__} with args {args} and kwargs {kwargs}')
result = func(*args, **kwargs)
print(f'{message}: {func.__name__} returned {result}')
return result
return wrapper
return decorator
@log('DEBUG')
def add(x, y):
return x + y
result = add(5, 3)
print(f'Result: {result}')
Real-Life Use Case
Decorator factories are used when the decorator needs to be configured with arguments. This is common in logging, where you might want to specify the log level, or in caching, where you might want to specify the cache expiration time. Another use case is access control, where the role required to call a function can be passed as an argument to the decorator.
Best Practices
functools.wraps to preserve the original function's metadata.
Interview Tip
Be prepared to explain the difference between a decorator and a decorator factory. Understand how the arguments are passed to the decorator factory and how the returned decorator is applied to the function. Also, be able to write a simple decorator factory from scratch.
When to Use Them
Use decorator factories when you need to parameterize the behavior of your decorators. This provides greater flexibility and allows you to reuse the same decorator with different configurations.
Memory Footprint
Decorator factories have a similar memory footprint to regular decorators. The overhead is minimal and is often outweighed by the benefits of code reuse and flexibility.
Alternatives
Alternatives to decorator factories include using class-based decorators or creating separate decorators for each configuration. However, decorator factories are often the most concise and elegant solution.
Pros
Cons
FAQ
-
Can I use multiple decorators on a single function?
Yes, you can apply multiple decorators to a single function. The decorators are applied from top to bottom, with the topmost decorator being applied first. -
How do I access the arguments passed to the original function inside the decorator?
The arguments passed to the original function are passed to thewrapperfunction. You can access them using*argsand**kwargs.