Decorators in Python are functions that modify the behavior of other functions. Sometimes, you may want to pass parameters to a decorator to customize its behavior. This is done by adding an extra layer of function nesting.
Decorators with arguments are widely used in logging, authentication, validation, and dynamic functionality.
Why Decorators with Arguments Are Important
- Make decorators more flexible and reusable
- Enable dynamic behavior customization
- Useful in web frameworks and APIs
- Allow parameterized logging or validation
Basic Syntax
def decorator_with_args(arg):
def decorator(func):
def wrapper(*args, **kwargs):
print(f"Decorator argument: {arg}")
return func(*args, **kwargs)
return wrapper
return decorator
@decorator_with_args("Hello")
def greet(name):
print(f"Hi {name}")
greet("Python")
Output:
Decorator argument: Hello
Hi Python
Example 1: Logging with Arguments
def log(level):
def decorator(func):
def wrapper(*args, **kwargs):
print(f"[{level}] Function {func.__name__} called with {args} {kwargs}")
return func(*args, **kwargs)
return wrapper
return decorator
@log("INFO")
def add(a, b):
return a + b
print(add(5, 3))
Output:
[INFO] Function add called with (5, 3) {}
8
Example 2: Authorization Decorator
def authorize(role):
def decorator(func):
def wrapper(user_role, *args, **kwargs):
if user_role != role:
print("Access Denied")
return
return func(*args, **kwargs)
return wrapper
return decorator
@authorize("admin")
def delete_user(user_id):
print(f"User {user_id} deleted")
delete_user("admin", 101) # Access granted
delete_user("guest", 102) # Access Denied
Example 3: Real-World Scenario – Timing Decorator with Arguments
import time
def timer(unit="seconds"):
def decorator(func):
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
end = time.time()
elapsed = end - start
if unit == "milliseconds":
elapsed *= 1000
print(f"Execution time: {elapsed:.2f} {unit}")
return result
return wrapper
return decorator
@timer("milliseconds")
def compute():
sum([i**2 for i in range(100000)])
compute()
Best Practices
✔ Use decorators with arguments for flexible, reusable code
✔ Keep wrapper functions simple
✔ Preserve function metadata with functools.wraps
✔ Avoid over-nesting decorators for readability
Conclusion
Python decorators with arguments allow dynamic and reusable modifications of function behavior. They are widely used in real-world applications such as logging, authentication, and performance measurement.
References
- Internal Reference: https://savanka.com/category/learn/python/
- External Reference: https://www.w3schools.com/python/