拆解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 result
return wrapper
return 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)
三、三层调用链
装饰器工厂的三层结构,对应“配置-绑定-执行”三个阶段:
- 配置层:
contract(pre=[...], post=[...])
调用工厂函数,传入条件参数,返回decorator函数(闭包捕获条件)。 - 绑定层:
decorator(double)
传入原函数,返回wrapper函数(闭包捕获原函数+条件)。 - 执行层:
wrapper(4)
调用包装函数,执行“检查-原函数-检查”逻辑,返回结果。
完整调用链等价写法:
(contract(pre=[is_positive], post=[returns_even])(double))(4)
总结
- 装饰器工厂本质是三层函数嵌套,@语法是函数调用的语法糖;
- 核心逻辑:
@factory(参数)→factory(参数)(原函数)→ 执行包装函数; - 关键:闭包保存状态、
*args/**kwargs透传参数、@wraps保留原函数信息。
被装饰函数 = 装饰器工厂(配置参数)(原函数),就能拆解所有带参数的装饰器。
浙公网安备 33010602011771号