Python装饰器进阶:5个高效使用场景与实战案例
一、装饰器核心概念回顾
装饰器是Python中一种强大的语法糖,它允许在不修改原函数代码的情况下,为函数添加额外的功能。本质上,装饰器是一个接收函数作为参数并返回新函数的高阶函数。
def simple_decorator(func):
def wrapper():
print("函数执行前操作")
func()
print("函数执行后操作")
return wrapper
@simple_decorator
def greet():
print("Hello, World!")
greet()
二、5个高级使用场景与案例
1. 带参数的装饰器
通过嵌套函数实现可配置的装饰器:
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 say_hello(name):
print(f"Hello, {name}!")
say_hello("Python开发者")
2. 类装饰器
使用类实现装饰器,可以更好地维护状态:
class TimerDecorator:
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwargs):
import time
start = time.time()
result = self.func(*args, **kwargs)
end = time.time()
print(f"{self.func.__name__} 执行耗时: {end-start:.4f}秒")
return result
@TimerDecorator
def calculate_sum(n):
return sum(range(n))
print(calculate_sum(1000000))
3. 缓存装饰器
实现函数结果的缓存,提升性能:
from functools import wraps
def cache_decorator(func):
cache = {}
@wraps(func)
def wrapper(*args):
if args in cache:
print("从缓存获取结果")
return cache[args]
result = func(*args)
cache[args] = result
return result
return wrapper
@cache_decorator
def fibonacci(n):
if n <= 1:
return n
return fibonacci(n-1) + fibonacci(n-2)
print(fibonacci(10))
4. 权限验证装饰器
Web开发中的常见应用:
def login_required(role="user"):
def decorator(func):
def wrapper(user, *args, **kwargs):
if not user.get("is_authenticated", False):
raise PermissionError("用户未登录")
if role == "admin" and not user.get("is_admin", False):
raise PermissionError("需要管理员权限")
return func(user, *args, **kwargs)
return wrapper
return decorator
@login_required(role="admin")
def delete_user(user, user_id):
print(f"管理员 {user['name']} 删除了用户 {user_id}")
user = {"name": "admin", "is_authenticated": True, "is_admin": True}
delete_user(user, 1001)
5. 日志记录装饰器
自动记录函数调用信息:
import logging
from functools import wraps
logging.basicConfig(level=logging.INFO)
def log_execution(func):
@wraps(func)
def wrapper(*args, **kwargs):
logging.info(f"开始执行: {func.__name__}")
try:
result = func(*args, **kwargs)
logging.info(f"成功执行: {func.__name__}")
return result
except Exception as e:
logging.error(f"执行失败: {func.__name__}, 错误: {str(e)}")
raise
return wrapper
@log_execution
def process_data(data):
if not data:
raise ValueError("数据不能为空")
return [x*2 for x in data]
process_data([1, 2, 3])
三、装饰器最佳实践
- 始终使用
@functools.wraps
保留原函数元信息 - 避免在装饰器中修改传入的参数
- 装饰器嵌套顺序会影响执行顺序
- 复杂的业务逻辑考虑使用类装饰器
- 为装饰器编写清晰的文档字符串