Python函数多次装饰后帮助信息丢失,是因为装饰器用新函数替换原函数导致元数据被覆盖;解决方法是每层装饰器内部包装函数均使用@functools.wraps(func)自动复制__name__、__doc__等属性。
Python 中函数被多次装饰后帮助信息丢失,是因为装饰器通常会用新函数替换原函数,导致
、
、函数名等元数据被覆盖。解决方法是让装饰器**保留原始函数的元数据**,核心是使用
。
用
保留元数据
这是最标准、最推荐的做法。每次写装饰器时,在内层包装函数上加上
,它会自动复制
、
、
、
等关键属性。
示例:
此时
正确显示:
立即学习
“
Python免费学习笔记(深入)
”;
Python 3.14.3
微软官方的 Python 扩展,是 VS Code 安装量最高的扩展(209M+)。集成 IntelliSense(通过 Pylance)、调试(通过 Python Debugger)、代码检查、格式化、重构和单元测试等功能。支持 Jupyter Notebook、虚拟环境管理和多 Python 版本切换。
下载
多层装饰时,每层都要用
如果装饰器嵌套三层(比如
→
→
→ 函数),那么 A、B、C 三个装饰器内部的包装函数都必须各自调用
。漏掉任意一层,元数据就会在那一层中断。
装饰器本身不加
→ 元
数据丢失
只在最外层加,中间层没加 → 中间层已覆盖,外层补救无效
每一层都加 → 原始函数的
和名字能穿透所有层级
检查是否生效的小技巧
调试时可快速验证:
→ 应输出
,不是
→ 应输出
→ 显示内容应和原始函数一致
不推荐的手动复制(仅作了解)
理论上可以手动赋值:
但容易遗漏属性(如
、
),且不可靠。
务必优先使用
。
help()docstringfunctools.wraps@functools.wraps@wraps(func)__name____doc____module____annotations__from functools import wraps
def log_calls(func):
@wraps(func) # ← 关键:保留原函数元数据
def wrapper(*args, *kwargs):
print(f"Calling {func.name}")
return func(args, **kwargs)
return wrapper
def add_one(func):
@wraps(func)
def wrapper(*args, *kwargs):
result = func(args, **kwargs)
return result + 1
return wrapper
@log_calls
@add_one
def square(x):
"""Return the square of x."""
return x * x
help(square)Help on function square in module __main__:square(x) Return the square of x.@wraps@A@B@C@wraps@wraps__doc__print(square.__name__)'square''wrapper'print(square.__doc__)"Return the square of x."help(square)def bad_decorator(func):
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
wrapper.__name__ = func.__name__
wrapper.__doc__ = func.__doc__
wrapper.__module__ = func.__module__
return wrapper
__annotations____dict__@functools.wraps