上一篇
Python装饰器保留函数元信息完整教程 - functools.wraps详解
- Python
- 2025-08-03
- 1954
Python装饰器如何保留原函数信息
为什么需要保留函数信息?
Python装饰器在修改函数行为时,会覆盖函数的元信息(如函数名、文档字符串等)。这会导致:
- 1. 函数名(__name__)变成装饰器内部函数名
- 2. 文档字符串(__doc__)丢失
- 3. 影响调试和日志输出
- 4. 破坏自省工具功能
解决方案:使用functools.wraps
Python标准库中的functools.wraps
装饰器可以解决这个问题:
from functools import wraps
def my_decorator(func):
@wraps(func) # 关键步骤:保留原函数信息
def wrapper(*args, **kwargs):
"""装饰器内部包装函数"""
print(f"调用函数: {func.__name__}")
return func(*args, **kwargs)
return wrapper
对比示例:使用wraps前后差异
未保留元信息的装饰器
def bad_decorator(func):
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
return wrapper
@bad_decorator
def example():
"""示例函数文档字符串"""
pass
print(example.__name__) # 输出:wrapper
print(example.__doc__) # 输出:None
使用wraps保留元信息
from functools import wraps
def good_decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
return wrapper
@good_decorator
def example():
"""示例函数文档字符串"""
pass
print(example.__name__) # 输出:example
print(example.__doc__) # 输出:示例函数文档字符串
保留元信息的工作原理
functools.wraps
实际上执行了以下操作:
def wraps(original_func):
def decorator(wrapper_func):
# 复制关键元数据
wrapper_func.__name__ = original_func.__name__
wrapper_func.__doc__ = original_func.__doc__
wrapper_func.__module__ = original_func.__module__
wrapper_func.__annotations__ = original_func.__annotations__
return wrapper_func
return decorator
实际上它会复制更多属性,包括:__qualname__, __module__, __annotations__等
高级用法:自定义元信息
在保留原信息基础上添加新元数据:
from functools import wraps
def versioned(version):
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
# 添加自定义元数据
wrapper.__version__ = version
return wrapper
return decorator
@versioned("1.2.0")
def api_handler():
"""处理API请求"""
pass
print(api_handler.__name__) # 输出:api_handler
print(api_handler.__version__) # 输出:1.2.0
实际应用场景
- Web框架路由:Flask/Django保留视图函数信息
- API版本控制:添加版本元数据同时保留文档
- 调试工具:在日志中显示原始函数名
- 文档生成:Sphinx等工具依赖函数元信息
最佳实践总结
- 始终在装饰器中使用
@wraps(func)
- 需要添加新元数据时,在
@wraps
之后设置 - 使用
inspect
模块验证元信息完整性 - 在类装饰器中同样适用:
@wraps(cls)
本文由ShenKua于2025-08-03发表在吾爱品聚,如有疑问,请联系我们。
本文链接:https://www.521pj.cn/20257235.html
发表评论