当前位置: 首页 > news >正文

拆解Python装饰器工厂:从语法糖到本质

拆解Python装饰器工厂:从语法糖到本质

拆解Python装饰器工厂:从语法糖到本质

装饰器工厂的核心可归结为函数嵌套调用 + 闭包传状态

一、示例

from functools import wraps# 1. 定义装饰器工厂
def contract(pre=None, post=None):def decorator(func):@wraps(func)  # 保留原函数元信息def wrapper(*args, **kwargs):# 前置检查for check in pre or []:if not check(*args, **kwargs):raise ValueError("前置条件失败")# 执行原函数result = func(*args, **kwargs)# 后置检查for check in post or []:if not check(result, *args, **kwargs):raise AssertionError("后置条件失败")return resultreturn wrapperreturn decorator# 2. 定义检查函数+被装饰函数
def is_positive(x): return x > 0
def returns_even(res, x): return res % 2 == 0@contract(pre=[is_positive], post=[returns_even])
def double(x): return x * 2# 3. 调用测试
print(double(4))   # ✅ 8
# print(double(-1)) # ❌ 抛ValueError

二、@语法糖的本质

@contract(pre=[...], post=[...]) 不是魔法,只是一行代码的简写:

# 装饰器语法 = 手动调用等价写法
double = contract(pre=[is_positive], post=[returns_even])(double)

三、三层调用链

装饰器工厂的三层结构,对应“配置-绑定-执行”三个阶段:

  1. 配置层contract(pre=[...], post=[...])
    调用工厂函数,传入条件参数,返回decorator函数(闭包捕获条件)。
  2. 绑定层decorator(double)
    传入原函数,返回wrapper函数(闭包捕获原函数+条件)。
  3. 执行层wrapper(4)
    调用包装函数,执行“检查-原函数-检查”逻辑,返回结果。

完整调用链等价写法:

(contract(pre=[is_positive], post=[returns_even])(double))(4)

总结

  1. 装饰器工厂本质是三层函数嵌套,@语法是函数调用的语法糖;
  2. 核心逻辑:@factory(参数)factory(参数)(原函数) → 执行包装函数;
  3. 关键:闭包保存状态、*args/**kwargs透传参数、@wraps保留原函数信息。

被装饰函数 = 装饰器工厂(配置参数)(原函数),就能拆解所有带参数的装饰器。