In Python, decorators are special functions that allow you to modify or extend the behavior of other functions or methods without changing their source code.
They are commonly used for logging, authentication, caching, performance measurement, and more.
Example: Logging Decorator
def log(func):
def wrapper(*args, **kwargs):
print(f"Calling {func.__name__} with {args}")
result = func(*args, **kwargs)
print(f"{func.__name__} returned {result}")
return result
return wrapper
@log
def add(a, b):
return a + b
print(add(2, 3))Here,
logis a decorator function that accepts another function (func) as input.- Inside
log, a new functionwrapperis defined. This function:- Prints the function name and arguments before calling the actual function.
- Calls the original function (
func(*args, **kwargs)) and stores the result. - Prints the result before returning it.
- The line
@logapplies the decorator to theaddfunction. This is shorthand for writing:add = log(add) - When
add(2, 3)is called, it actually runs wrapper, adding the extra logging functionality.
Output:
Calling add with (2, 3)
add returned 5
5Why Use Decorators?
- Add extra functionality without modifying original code
- Keep code clean and reusable
- Great for cross-cutting concerns like logging, access control, validation
Best Practices
- Always use
functools.wrapsto preserve the original function’s metadata. - Keep decorators small and reusable.
- Avoid nesting too many decorators for readability.
When to Use Decorators
- Logging and debugging
- Authentication and authorization
- Measuring performance (timing functions)
- Input validation
- Caching results of expensive computations
👉 Next tutorial: Python Class Methods