functools.wraps 不可省略,否则被装饰函数的 name__、__doc__、__module__、__qualname__、__annotations 等元信息会丢失,导致调试、文档生成、类型检查等失败。

为什么 functools.wraps 不能省?
不加 functools.wraps 的装饰器,会让被装饰函数的元信息(__name__、__doc__、__module__ 等)变成内层包装函数的信息,导致调试、文档生成、反射等场景出错。这不是风格问题,是实际功能断裂。
functools.wraps 到底复制了哪些属性?
它本质是调用 update_wrapper,默认同步以下关键属性:
- __module__:确保 help() 和日志里显示正确的模块路径
- __name__:让断点调试、性能分析工具(如 cProfile)能识别原函数名
- __qualname__:支持嵌套函数和类方法的正确路径表示
- __doc__:保证 help() 和 IDE 悬停提示显示原始 docstring
- __annotations__:类型提示不会丢失,对 mypy、pylance 等工具至关重要
不加 @wraps(func) 的典型错误现象
常见于日志、测试、框架集成等依赖函数元信息的场景:
- help(my_decorated_func) 显示的是 wrapper 的空 docstring,而非原函数说明
- 单元测试中用 self.assertEqual(my_func.__name__, "expected_name") 直接失败
- FastAPI 或 Flask 路由函数丢失 __name__ 后,自动文档(Swagger)无法正确归类接口
- 使用 inspect.signature() 获取参数时,返回的是包装函数的签名,不是原始函数的
一个最小可验证示例
对比加与不加 @wraps 的行为差异:
from functools import wrapsdef log_calls(func): def wrapper(*args, *kwargs): print(f"Calling {func.name}") return func(args, **kwargs)
缺少 @wraps(func) → 元信息丢失
return wrapperdef log_calls_fixed(func): @wraps(func) def wrapper(*args, *kwargs): print(f"Calling {func.name}") return func(args, **kwargs) return wrapper
@log_calls def add(a, b): """Return sum of a and b.""" return a + b
@log_calls_fixed def multiply(a, b): """Return product of a and b.""" return a * b
执行
print(add.__name__, add.__doc__)输出wrapper None;而multiply.__name__是multiply,multiply.__doc__正确为"Return product of a and b."。
开源电子商务系统(网店) iWebShop下载iWebShop基于iWebSI框架开发,在获得iWebSI技术平台库支持的条件下,iWebShop可以轻松满足用户量级百万至千万级的大型电子商务网站的性能要求。站点的集群与分布式技术(分布式计算与存储/高可用性/负载均衡)被屏蔽在SI 平台之内,基于iWebShop并且按照SI平台库扩展规范开发的新增功能模块,也将同时获得这种超级计算与处理的能力。作为开源的LAMP电子商务系统,iWebShop
元信息丢失的问题在简单脚本里可能无感,但一旦进入团队协作、自动化工具链或框架集成环节,就会变成难以定位的隐性故障点。
立即学习“Python免费学习笔记(深入)”;










