当前位置: 首页 > news >正文

装饰器@wraps(func)详解

在这里插入图片描述

1. @wraps(func) 的核心作用

@wraps 是 Python 标准库 functools 提供的装饰器,用于保留被装饰函数的原始元信息
它通过将原函数的 __name____doc____module__ 等属性复制到装饰器内部的包装函数中,避免装饰器对函数身份信息的“掩盖”。


2. 元信息丢失的问题(无 @wraps 时)

示例代码
def simple_decorator(func):def wrapper(*args, **kwargs):"""Wrapper docstring"""return func(*args, **kwargs)return wrapper@simple_decorator
def say_hello():"""Original docstring"""print("Hello!")print(say_hello.__name__)  # 输出什么?
print(say_hello.__doc__)   # 输出什么?
输出结果
wrapper          # 函数名变为装饰器内部的 wrapper
Wrapper docstring  # 文档字符串被覆盖
问题分析
  • 被装饰后,函数的 __name____doc__ 变成了装饰器内部 wrapper 的信息。
  • 这会导致调试困难(日志中显示 wrapper 而非原函数名)、文档工具(如 Sphinx)无法正确生成文档。

3. 使用 @wraps(func) 修复元信息

改进代码
from functools import wrapsdef better_decorator(func):@wraps(func)  # 关键点:复制元信息def wrapper(*args, **kwargs):"""Wrapper docstring"""return func(*args, **kwargs)return wrapper@better_decorator
def say_hello():"""Original docstring"""print("Hello!")print(say_hello.__name__)  # 输出 'say_hello'
print(say_hello.__doc__)   # 输出 'Original docstring'
输出结果
say_hello        # 函数名保留原名称
Original docstring  # 文档字符串未被覆盖
关键变化
  • @wraps(func) 将原函数 say_hello 的元信息复制到 wrapper 函数。
  • 调试和文档工具看到的是原函数的元数据,而非装饰器内部的实现细节。

4. @wraps 保留的具体属性

@wraps 默认会复制以下属性(完整列表见 functools.wraps 文档):

属性名作用
__name__函数名
__doc__文档字符串
__module__所在模块名
__annotations__类型注解
__dict__其他自定义属性

5. 在类方法装饰器中的必要性

原问题代码分析
class RouterClient:@keep_alivedef execute(self, command):"""Send a command to the device"""return self.conn.send_command(command)
  • @wraps
    • execute.__name__ 会变成 "wrapper"
    • help(RouterClient.execute) 显示装饰器的文档而非原方法文档。
  • @wraps
    • 保留原始方法名和文档,便于其他开发者理解代码。

6. 验证 @wraps 效果的实用技巧

检查函数身份
def check_metadata(func):print(f"Function name: {func.__name__}")print(f"Docstring: {func.__doc__}")print(f"Is it a wrapper? {'wrapper' in func.__name__}")check_metadata(say_hello)  # 装饰后仍显示原函数信息
输出示例(使用 @wraps 时)
Function name: say_hello
Docstring: Original docstring
Is it a wrapper? False

7. 为什么装饰器会覆盖元信息?

  • Python 装饰器的本质@decorator 等价于 func = decorator(func)
  • 装饰器返回的新函数(如 wrapper)会替换原函数,而函数的元信息绑定在函数对象本身。
  • @wraps 通过 functools.update_wrapper 实现属性复制,解决身份丢失问题。

8. 总结

  • 何时用 @wraps:任何时候编写装饰器时,除非故意想隐藏原函数信息。
  • 核心价值
    • 调试时显示有意义的函数名(而非 wrapper)。
    • 保留文档字符串和类型注解,提升代码可维护性。
    • 兼容依赖元信息的工具(如测试框架、文档生成器)。

相关文章:

  • MFC自定义控件开发与使用指南
  • (1)大模型的提示词工程实践技巧---LLM输出配置详解
  • 动态功耗与静态功耗
  • WGDI-分析WGD及祖先核型演化的集成工具-文献精读126
  • 【Mytais系列】介绍、核心概念
  • 【自然语言处理与大模型】使用Xtuner进行模型合并与导出
  • Github 2025-05-03 Rust开源项目日报 Top10
  • (即插即用模块-Attention部分) 六十三、(2024 CVPR) MLKA 多尺度大核注意力
  • 我写了一个分析 Linux 平台打开文件描述符跨进程传递的工具
  • 学习黑客网络安全法
  • Docker与WSL2如何清理
  • WebRTC 服务器之Janus架构分析
  • 【JAVA】数组与内存模型:二维数组底层实现(9)
  • 2.2 矩阵
  • NV203NV207SSD固态闪存NV208NV213
  • Maven 实现多模块项目依赖管理
  • neo4j初尝试
  • YOLOv11改进:利用RT-DETR主干网络PPHGNetV2助力轻量化目标检测
  • Excel-CLI:终端中的轻量级Excel查看器
  • 普通IT的股票交易成长史--20250502 突破(2)
  • 过半中国上市公司去年都在“扩编”,哪些公司人效最高
  • 赵乐际:深入学习贯彻习近平生态文明思想,推动森林法全面有效贯彻实施
  • 抗战回望19︱《中国工程师学会四川考察团报告》:“将来重工业所在,以四川为最适宜之地点”
  • 同路人才是真朋友——驻南苏丹使馆援助东赤道州人道主义物资交接仪式侧记
  • 浙江医生举报3岁男童疑遭生父虐待,妇联:已跟爷爷奶奶回家
  • 俄罗斯期望乌克兰在停火期间采取行动缓和局势