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

装饰器@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)。
    • 保留文档字符串和类型注解,提升代码可维护性。
    • 兼容依赖元信息的工具(如测试框架、文档生成器)。
http://www.xdnf.cn/news/3637.html

相关文章:

  • 伊甸园之东: 农业革命与暴力的复杂性
  • Learning vtkjs之Cutter
  • 有向图强连通分量好题分享(一)
  • 【深度学习的灵魂】图片布局生成模型LayoutPrompt(2)·布局序列化模块
  • 如何通过文理工三类AI助理赋能HI,从而,颠覆“隔行如隔山”的旧观念和“十万小时定律”的成长限制
  • 快速掌握--cursor
  • 深入解析 Stacking:集成学习的“超级英雄联盟
  • 排查 EF 保存数据时提示:Validation failed for one or more entities 的问题
  • 以梦为舟,共赴中医星辰大海
  • 【Mytais系列】Type模块:源码
  • MySQL快速入门篇---数据库约束
  • 【计算机视觉】三维重建: MVSNet:基于深度学习的多视图立体视觉重建框架
  • 驱动精灵v9.7(含网卡版)驱动工具软件下载及安装教程
  • 360驱动大师v2.0(含网卡版)驱动工具软件下载及安装教程
  • The Traitor King (10 player 25 player)
  • 【网络编程】HTTP(超文本传输协议)详解
  • 文献总结:TPAMI端到端自动驾驶综述——End-to-End Autonomous Driving: Challenges and Frontiers
  • 《解锁Windows下GCC升级密码,开启高效编程新旅程》
  • 游戏引擎学习第255天:构建配置树
  • 【AI面试准备】Testim.io自动化测试工具使用指南
  • C++ 友元:打破封装的钥匙
  • 【Linux】线程控制
  • 【PINN】DeepXDE学习训练营(12)——operator-antiderivative_aligned_pideeponet.py
  • 0902Redux_状态管理-react-仿低代码平台项目
  • Go小技巧易错点100例(二十八)
  • LeetCode240. 搜索二维矩阵 II(巧妙转换)
  • 【AI论文】DeepCritic:使用大型语言模型进行有意识的批判
  • Vscode+git笔记
  • 【Bootstrap V4系列】学习入门教程之 组件-徽章(Badge)和面包屑导航(Breadcrumb)
  • 【Java Lambda表达式详解】