Table Of Contents
Problem
You want to add functionality like logging, timing, or authentication to multiple functions without repeating code in each function.
Solution
# Basic decorator
def my_decorator(func):
def wrapper():
print("Before function")
func()
print("After function")
return wrapper
@my_decorator
def say_hello():
print("Hello!")
say_hello()
# Before function
# Hello!
# After function
# Decorator with arguments
def timer(func):
import time
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print(f"{func.__name__} took {end - start:.4f} seconds")
return result
return wrapper
@timer
def slow_function(n):
import time
time.sleep(1)
return n * 2
result = slow_function(5) # Shows timing info
# Decorator with parameters
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(3)
def greet(name):
print(f"Hello {name}")
greet("Alice") # Prints 3 times
# Class-based decorator
class CountCalls:
def __init__(self, func):
self.func = func
self.count = 0
def __call__(self, *args, **kwargs):
self.count += 1
print(f"Call {self.count} of {self.func.__name__}")
return self.func(*args, **kwargs)
@CountCalls
def add(x, y):
return x + y
add(1, 2) # Call 1 of add
add(3, 4) # Call 2 of add
# Preserve function metadata
from functools import wraps
def log_calls(func):
@wraps(func) # Preserves original function's metadata
def wrapper(*args, **kwargs):
print(f"Calling {func.__name__}")
return func(*args, **kwargs)
return wrapper
@log_calls
def calculate(x, y):
"""Add two numbers"""
return x + y
print(calculate.__name__) # calculate
print(calculate.__doc__) # Add two numbers
Explanation
Decorators are functions that take another function and extend its behavior. Use @decorator_name
above function definitions for cleaner syntax.
Always use *args, **kwargs
in wrapper functions to handle any arguments. Use @wraps
from functools to preserve the original function's metadata like name and docstring.
Share this article
Add Comment
No comments yet. Be the first to comment!