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 thewrapper
function. You can access them using*args
and**kwargs
.