装饰器的应用场景
- 附加功能
- 数据的清理或添加:
- 函数参数类型验证 @require_ints 类似请求前拦截
- 数据格式转换 将函数返回字典改为 JSON/YAML 类似响应后篡改
- 为函数提供额外的数据 mock.patch
- 函数注册
- 在任务中心注册一个任务
- 注册一个带信号处理器的函数
不同应用场景下装饰器实现
函数注册表
简单注册表
funcs = [] def register(func): funcs.append(func) return func @register def a(): return 3 @register def b(): return 5 # 访问结果 result = [func() for func in funcs]
注册表隔离(使用类的不同实例)
class Registry(object): def __init__(self): self._funcs = [] def register(self, func): self._funcs.append(func) def run_all(self): return [func() for func in self._funcs] r1 = Registry() r2 = Registry() @r1.register def a(): return 3 @r2.register def b(): return 5 @r1.register @r2.register
执行时封装代码
类型检查
from functools import wraps def require_ints(func): @wraps(func) # 将func的信息复制给inner def inner(*args, **kwargs): for arg list(args) + list(kwargs.values()): if not isinstance(arg, int: raise TypeError("{} 只接受int类型参数".format(func.__name__) return func(*args, **kwargs) return inner
用户验证
from functools import wraps class User(object): def __init__(self, username, email): self.username = username self.email = email class AnonymousUser(object): def __init__(self): self.username = self.email = None def __nonzero__(self): # 将对象转换为bool类型时调用 return False def requires_user(func): @wraps(func) def inner(user, *args, **kwargs): # 由于第一个参数无法支持self, 该装饰器不支持装饰类 if user and isinstance(user, User): return func(use, *args, **kwargs) else: raise ValueError("非合法用户") return inner
输出格式化
import json from functools import wraps def json_output(func): # 将原本func返回的字典格式转为返回json字符串格式 @wrap(func) def inner(*args, **kwargs): return json.dumps(func(*args, **kwargs)) return inner
异常捕获
import json from functools import wraps class Error1(Exception): def __init__(self, msg): self.msg = msg def __str__(self): return self.msg def json_output(func): @wrap(func) def inner(*args, **kwargs): try: result = func(*args, **kwargs) excep