general summary
In Python, a decorator is a design pattern and a feature that allows you to modify functions and methods dynamically.
This is done primarily to keep the code clean, maintainable, and DRY (Don’t Repeat Yourself).
How Decorators Work
Decorators wrap a target function, allowing you to execute custom code before and after that function.
They are typically higher-order functions that take a function as an argument and return a new function.
This paradigm of “functions that modify functions” is often referred to as metaprogramming.
Common Use Cases
Authorization and Authentication: Control user access.
Logging: Record function calls and their parameters.
Caching: Store previous function results for quick access.
Validation: Verify input parameters or function output.
Task Scheduling: Execute a function at a specific time or on an event.
Counting and Profiling: Keep track of the number of function calls and their execution time.
decorator example
from functools import wraps
1. Basic Decorator
def my_decorator(func):
@wraps(func) # Ensures the original function's metadata is preserved
def wrapper(*args, **kwargs):
print('Something is happening before the function is called.')
result = func(*args, **kwargs)
print('Something is happening after the function is called.')
return result
return wrapper
@my_decorator
def say_hello():
print('Hello!')
say_hello()
2. Decorators with Arguments
def decorator_with_args(arg1, arg2):
def actual_decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
print(f'Arguments passed to decorator: {arg1}, {arg2}')
result = func(*args, **kwargs)
return result
return wrapper
return actual_decorator
@decorator_with_args('arg1', 'arg2')
def my_function():
print('I am decorated!')
my_function()Role of functools.wraps
When defining decorators, particularly those that return functions, it is good practice to use @wraps(func) from the functools module.
This ensures that the original function’s metadata, such as its name and docstring, is preserved.