Python装饰器通过函数替换实现行为增强:用新包装函数替代原函数,控制执行流程并保留原函数为闭包变量,但默认导致元信息丢失,需用@functools.wraps修复。

Python 装饰器本身不直接“改变”原函数的行为,而是用一个新函数替换了它——这个新函数在调用时,可以执行额外逻辑(如日志、校验、缓存),再决定是否、何时、如何调用原函数。行为变化的根源在于函数对象被重新绑定到了装饰后的版本。
装饰器本质是函数替换
使用 @decorator 语法糖等价于:
func = decorator(func)
也就是说,变量 func 不再指向原来的函数对象,而是指向装饰器返回的新可调用对象(通常是闭包或类实例)。后续所有对 func() 的调用,实际执行的是这个新对象的逻辑。
立即学习“Python免费学习笔记(深入)”;
新函数控制执行流程
典型的装饰器会在内部定义一个包装函数(wrapper),它:
- 接收与原函数一致的参数(通过
*args, **kwargs) - 可在调用原函数前插入任意代码(例如打印时间、检查权限)
- 可选择不调用原函数(比如权限不足时直接返回错误)
- 可修改传入参数或处理返回值(例如自动序列化响应)
- 可在调用后添加清理逻辑(如关闭数据库连接)
原函数依然存在,只是被“包裹”了
原函数通常作为自由变量保留在 wrapper 的闭包中(nonlocal 作用域),并未被销毁。你可以通过 wrapper.__wrapped__(如果装饰器遵循标准协议)或手动保存的引用访问它。但默认情况下,外部调用走的都是 wrapper 这一层。
副作用:函数元信息丢失
由于替换为新函数,原函数的 __name__、__doc__、__module__ 等属性默认变成 wrapper 的,这会影响调试、文档生成和反射。解决方法是用 @functools.wraps(func) 修饰 wrapper,自动复制这些属性。

