Python functools.wraps 解决了什么问题?

12次阅读

functools.wraps 解决了装饰器导致原函数元信息丢失的问题,自动将 name__、__doc__、__module 等关键属性从被装饰函数复制到包装函数,确保调试、帮助系统、ide 和框架正常工作。

Python functools.wraps 解决了什么问题?

functools.wraps 解决了装饰器覆盖原函数元信息的问题。

被装饰函数的 __name__、__doc__ 等属性会丢失

不使用 @wraps 时,装饰器内部通常返回一个新函数(闭包),这个新函数取代了原函数。结果是:
func.__name__ 变成装饰器里内层函数的名字(比如 'wrapper'
func.__doc__ 变成内层函数的文档字符串,不是原函数的
func.__module__func.__annotations__ 等也可能出错或为空

影响调试、帮助系统和工具

这些元信息丢失会导致:
help(func) 显示错误的函数名和说明
– IDE 自动补全或跳转可能指向装饰器内部,而非原始定义位置
– 日志中记录函数名变成 wrapper,难以定位实际逻辑
– 某些依赖函数签名的框架(如 flask 路由、click 命令)可能行为异常

wraps 的作用就是批量复制关键属性

@wraps(func) 是一个装饰器工厂,它会把被装饰函数的以下属性自动拷贝到包装函数上:
__module__
__name__
__qualname__
__doc__
__annotations__
– 还有 __dict__ 中的部分内容

本质是调用 functools.update_wrapper(wrapper, wrapped),但更简洁易用。

正确写法示例

对比两种写法:

❌ 不加 wraps:

def my_decorator(f):     def wrapper(*args, **kwargs):         print("before")         result = f(*args, **kwargs)         print("after")         return result     return wrapper 

@my_decorator def say_hello(): """Print hello""" print("hello")

say_hello.__name__'wrapper'say_hello.__doc__None

立即学习Python免费学习笔记(深入)”;

✅ 加 wraps:

from functools import wraps 

def my_decorator(f): @wraps(f) # 关键一行 def wrapper(*args, *kwargs): print("before") result = f(args, **kwargs) print("after") return result return wrapper

此时 say_hello.__name__ 仍是 'say_hello'say_hello.__doc__ 正确显示 "Print hello"

text=ZqhQzanResources