装饰器是 Python 中用于动态增强函数或类功能的工具,其核心思想是在不修改原有代码的前提下增加新功能。以下是装饰器的详细解析:
一、装饰器工作原理
核心机制:装饰器本质是一个可调用对象(函数或类),通过闭包和函数替换实现功能扩展。
def decorator(func):
def wrapper(*args, **kwargs):
print("Before execution")
result = func(*args, **kwargs) # 调用原函数
print("After execution")
return result
return wrapper
@decorator
def target_function():
print("Target function executed")
# 调用 target_function() 实际执行的是 wrapper()
二、函数装饰器 vs 类装饰器
特性 | 函数装饰器 | 类装饰器 |
---|---|---|
实现方式 | 通过嵌套函数和闭包 | 通过类的 __call__ 方法实现实例可调用 |
状态管理 | 使用闭包变量或 nonlocal 关键字 | 使用实例属性 |
可扩展性 | 适合简单逻辑 | 适合需要维护复杂状态的场景 |
装饰目标 | 主要装饰函数,也可装饰类 | 可装饰函数或类 |
典型应用场景 | 日志、计时、权限校验 | 需要多次初始化的装饰逻辑 |
类装饰器示例:
class ClassDecorator:
def __init__(self, func):
self.func = func
self.call_count = 0 # 维护状态
def __call__(self, *args, **kwargs):
self.call_count += 1
print(f"Call count: {self.call_count}")
return self.func(*args, **kwargs)
@ClassDecorator
def my_func():
print("Function executed")
三、自定义复杂装饰器技巧
1. 带参数的装饰器
需三层嵌套结构:
def param_decorator(level="INFO"):
def actual_decorator(func):
def wrapper(*args, **kwargs):
print(f"[{level}] Entering {func.__name__}")
return func(*args, **kwargs)
return wrapper
return actual_decorator
@param_decorator(level="DEBUG")
def debug_function():
pass
2. 装饰器堆叠
执行顺序从下往上:
@decorator1
@decorator2
def func():
pass
# 等价于 decorator1(decorator2(func))()
3. 保留元数据
使用 functools.wraps
保持原函数信息:
from functools import wraps
def meta_preserving_decorator(func):
@wraps(func) # 关键语句
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
return wrapper
四、高级应用场景
1. 性能统计装饰器
import time
def timer(func):
@wraps(func)
def wrapper(*args, **kwargs):
start = time.perf_counter()
result = func(*args, **kwargs)
duration = time.perf_counter() - start
print(f"{func.__name__} took {duration:.4f} seconds")
return result
return wrapper
2. 访问控制装饰器
def admin_required(func):
@wraps(func)
def wrapper(user, *args, **kwargs):
if not user.is_admin:
raise PermissionError("Admin access required")
return func(user, *args, **kwargs)
return wrapper
@admin_required
def delete_database(user):
print("Database deleted!")
3. 类方法装饰器
def class_decorator(cls):
cls.new_method = lambda self: print("Added method")
return cls
@class_decorator
class MyClass:
pass
obj = MyClass()
obj.new_method() # 输出 "Added method"
五、关键注意事项
- 装饰器执行时机:在模块导入时立即执行装饰逻辑,而非函数调用时
- 装饰器顺序:离函数近的装饰器先执行(由内到外)
- 异常处理:装饰器中需合理处理异常传播
通过灵活组合这些技术,可以创建出适应各种场景的强大装饰器,实现代码的优雅复用和功能扩展。