Practical Use Cases
import time
import functools
def timer(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs)
end_time = time.time()
print(f"{func.__name__} executed in {end_time - start_time:.4f} seconds")
return result
return wrapper
@timer
def complex_calculation(n):
return sum(i**2 for i in range(n))
complex_calculation(10000)
Authentication and Authorization
def require_auth(role):
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
current_user = get_current_user()
if current_user.role == role:
return func(*args, **kwargs)
else:
raise PermissionError("Unauthorized access")
return wrapper
return decorator
@require_auth('admin')
def delete_user(user_id):
## User deletion logic
pass
Caching Decorator
def memoize(func):
cache = {}
@functools.wraps(func)
def wrapper(*args):
if args not in cache:
cache[args] = func(*args)
return cache[args]
return wrapper
@memoize
def fibonacci(n):
if n < 2:
return n
return fibonacci(n-1) + fibonacci(n-2)
Decorator Use Case Comparison
Use Case |
Purpose |
Key Benefits |
Logging |
Track function calls |
Debugging, monitoring |
Caching |
Store function results |
Performance optimization |
Authentication |
Control access |
Security management |
Retry Mechanism |
Handle transient failures |
Improved reliability |
Retry Mechanism Decorator
def retry(max_attempts=3, delay=1):
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
attempts = 0
while attempts < max_attempts:
try:
return func(*args, **kwargs)
except Exception as e:
attempts += 1
if attempts == max_attempts:
raise
time.sleep(delay)
return wrapper
return decorator
@retry(max_attempts=3)
def unstable_network_call():
## Simulated network operation
pass
Decorator Workflow
graph TD
A[Original Function] --> B{Decorator Applied}
B --> |Performance Tracking| C[Timing Measurement]
B --> |Authentication| D[Role Verification]
B --> |Caching| E[Result Memoization]
B --> |Retry Mechanism| F[Error Handling]
Best Practices for LabEx Developers
- Use decorators to separate cross-cutting concerns
- Keep decorators lightweight and focused
- Preserve function metadata with
functools.wraps
- Test decorated functions thoroughly
- Consider performance implications
By mastering these practical use cases, LabEx Python developers can write more modular, efficient, and maintainable code.