Python Decorators Explained Simply
Decorators are functions that modify the behavior of other functions. They use the @decorator syntax to add functionality without changing the original function's code.
Basic Decorator
def timer(func):
def wrapper(*args, **kwargs):
import time
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print(f"{func.__name__} took {end - start:.2f} seconds")
return result
return wrapper
@timer
def slow_function():
import time
time.sleep(2)
return "Done"
slow_function() # Prints: slow_function took 2.00 seconds
Logging Decorator
def log_calls(func):
def wrapper(*args, **kwargs):
print(f"Calling {func.__name__} with args={args}, kwargs={kwargs}")
result = func(*args, **kwargs)
print(f"{func.__name__} returned {result}")
return result
return wrapper
@log_calls
def add(a, b):
return a + b
add(3, 5)
# Output:
# Calling add with args=(3, 5), kwargs={}
# add returned 8
Multiple Decorators
def uppercase(func):
def wrapper(*args, **kwargs):
result = func(*args, **kwargs)
return result.upper()
return wrapper
def exclaim(func):
def wrapper(*args, **kwargs):
result = func(*args, **kwargs)
return result + "!"
return wrapper
@exclaim
@uppercase
def greet(name):
return f"hello {name}"
print(greet("alice")) # Output: HELLO ALICE!
Decorator with Arguments
def repeat(times):
def decorator(func):
def wrapper(*args, **kwargs):
for _ in range(times):
result = func(*args, **kwargs)
return result
return wrapper
return decorator
@repeat(times=3)
def say_hello():
print("Hello!")
say_hello()
# Output:
# Hello!
# Hello!
# Hello!
Practical Use Cases
- Timing: Measure function execution time
- Logging: Track function calls and arguments
- Authentication: Check user permissions before execution
- Caching: Store results for repeated calls (memoization)
- Validation: Verify input parameters
Pro Tip: Use functools.wraps to preserve the original function's metadata. This keeps __name__ and __doc__ intact when using decorators.
← Back to Python Tips