以下是 Python 装饰器模式 的详细用法解析与实用示例,涵盖函数装饰器、类装饰器及多层嵌套场景,帮助灵活扩展对象功能:
一、装饰模式的核心思想
- 定义:动态地为对象添加额外职责,且不改变其原有结构。
- 优势:避免继承导致的类爆炸,支持运行时功能组合。
- Python特性:通过
@
语法糖简化实现,本质是 高阶函数 或 类包装。
二、函数装饰器实现
1. 基础装饰器(无参)
def logger(func): def wrapper(*args, **kwargs): print(f"开始执行: {func.__name__}") result = func(*args, **kwargs) print(f"执行结束: {func.__name__}") return result return wrapper @logger def add(a, b): return a + b print(add(2, 3)) # 输出: # 开始执行: add # 执行结束: add # 5
2. 带参数的装饰器
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") # 输出: # Hello, Alice! # Hello, Alice! # Hello, Alice!
三、类装饰器实现
1. 装饰器类(基于 __call__
方法)
class Timer: 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:.2f}秒") return result @Timer def heavy_computation(n): return sum(i*i for i in range(n)) heavy_computation(10**6) # 输出: heavy_computation 耗时: 0.12秒
2. 装饰器类(带参数)
class PermissionCheck: def __init__(self, role): self.role = role def __call__(self, func): def wrapper(*args, **kwargs): if self.role == "admin": return func(*args, **kwargs) else: raise PermissionError("权限不足") return wrapper @PermissionCheck(role="admin") def delete_file(filename): print(f"删除文件: {filename}") delete_file("test.txt") # 输出: 删除文件: test.txt @PermissionCheck(role="user") def read_file(filename): print(f"读取文件: {filename}") read_file("test.txt") # 抛出 PermissionError
四、多层装饰器执行顺序
装饰器按 从下到上 的顺序应用:
@decorator1 @decorator2 def my_func(): pass # 等价于: my_func = decorator1(decorator2(my_func))
示例:
def bold(func): def wrapper(): return "<b>" + func() + "</b>" return wrapper def italic(func): def wrapper(): return "<i>" + func() + "</i>" return wrapper @bold @italic def say_hello(): return "Hello" print(say_hello()) # 输出: <b><i>Hello</i></b>
五、装饰器的典型应用场景
- 日志记录与性能监控
跟踪函数执行时间和参数。 - 权限验证
限制接口访问权限(如用户角色检查)。 - 缓存与记忆化
存储函数结果避免重复计算:from functools import lru_cache @lru_cache(maxsize=128) def fibonacci(n): if n < 2: return n return fibonacci(n-1) + fibonacci(n-2)
- 路由注册(Web框架)
Flask 框架的路由装饰器:@app.route("/") def home(): return "Welcome"
- 输入验证与格式化
确保函数参数符合预期:def validate_int_args(func): def wrapper(*args): if all(isinstance(arg, int) for arg in args): return func(*args) else: raise ValueError("参数必须为整数") return wrapper
六、注意事项与调试技巧
- 保留元信息
使用functools.wraps
保持原函数属性(如__name__
):from functools import wraps def debug(func): @wraps(func) def wrapper(*args, **kwargs): print(f"调用 {func.__name__}") return func(*args, **kwargs) return wrapper
- 处理带状态的装饰器
类装饰器适合需保存状态的场景(如计数器):class Counter: def __init__(self, func): self.func = func self.count = 0 def __call__(self, *args, **kwargs): self.count += 1 print(f"执行次数: {self.count}") return self.func(*args, **kwargs) @Counter def example(): pass
- 避免循环装饰
多层装饰可能引发意外行为,需谨慎设计执行顺序。
总结
Python 装饰器模式通过 高阶函数 或 类包装 实现功能扩展,结合 @
语法糖可显著提升代码可读性。合理使用装饰器能实现以下目标:
- 代码复用:抽离通用逻辑(如日志、权限)。
- 关注点分离:业务代码与辅助功能解耦。
- 动态扩展:运行时灵活组合功能模块。
掌握装饰器模式是编写优雅 Python 代码的关键技能!