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

@wraps(func)

@wraps(func) 是 Python 标准库 functools 模块提供的一个装饰器,主要用于保留被装饰函数的元信息(metadata)。当我们使用自定义装饰器包装函数时,被装饰后的函数会丢失原函数的名称、文档字符串等信息,而 @wraps(func) 可以解决这个问题。

为什么需要 @wraps(func)

先看一个不使用 @wraps 的例子,观察装饰器对函数元信息的影响:

def my_decorator(func):def wrapper(*args, **kwargs):"""这是 wrapper 函数的文档字符串"""return func(*args, **kwargs)return wrapper@my_decorator
def original_func():"""这是原函数的文档字符串"""print("原函数执行")# 查看被装饰后的函数信息
print("函数名:", original_func.__name__)  # 输出:wrapper(而非 original_func)
print("文档字符串:", original_func.__doc__)  # 输出:这是 wrapper 函数的文档字符串(而非原函数的)

可以看到,被装饰后的 original_func 实际上变成了 wrapper 函数,因此它的元信息(__name____doc__ 等)也被替换成了 wrapper 的信息。这会导致:

  • 调试时难以识别函数身份;
  • 生成文档时无法正确提取原函数的说明;
  • 依赖函数元信息的代码(如反射)出现异常。

@wraps(func) 的作用

@wraps(func) 的本质是将原函数 func 的元信息“复制”到装饰器内部的 wrapper 函数上,让 wrapper 函数看起来更像原函数。

修改上面的例子,添加 @wraps(func)

from functools import wrapsdef my_decorator(func):@wraps(func)  # 保留原函数元信息def wrapper(*args, **kwargs):"""这是 wrapper 函数的文档字符串"""return func(*args, **kwargs)return wrapper@my_decorator
def original_func():"""这是原函数的文档字符串"""print("原函数执行")# 再次查看被装饰后的函数信息
print("函数名:", original_func.__name__)  # 输出:original_func(正确保留)
print("文档字符串:", original_func.__doc__)  # 输出:这是原函数的文档字符串(正确保留)

此时,original_func 的元信息被正确保留,解决了装饰器导致的元信息丢失问题。

@wraps 复制的元信息包括:

@wraps 会将原函数的以下核心元信息复制到 wrapper 函数:

  • __name__:函数名称;
  • __doc__:文档字符串(docstring);
  • __module__:函数所在的模块;
  • __annotations__:函数的参数和返回值注解;
  • __defaults__:函数的参数默认值;
  • 其他与函数身份相关的属性。

实际应用场景

@wraps 在以下场景中尤为重要:
1.** 调试 :确保调试工具(如 pdb)显示的是原函数名,而非 wrapper
2.
文档生成 :自动文档工具(如 Sphinx)能正确提取原函数的文档字符串;
3.
装饰器嵌套 :多层装饰器时,保留元信息可避免身份混淆;
4.
依赖元信息的框架 **:某些框架(如 Flask、Django)会通过函数名或文档字符串实现特定功能,需确保元信息正确。

总结

@wraps(func) 是装饰器开发中的“最佳实践”,它的作用是保留被装饰函数的元信息,避免因装饰器包装导致函数身份、文档等信息丢失。使用时只需将其放在装饰器内部的 wrapper 函数上方,并传入原函数 func 作为参数即可。

在之前的“递归计时器装饰器”中,@wraps(func) 确保了被装饰的递归函数(如 factorialfibonacci)在调试或查看元信息时,仍能正确显示其原始名称和文档,而不是内部的 wrapper 函数信息。

http://www.hskmm.com/?act=detail&tid=31697

相关文章:

  • 递归函数的精确时间统计
  • [HZOI]CSP-S模拟32
  • 《植物大战僵尸融合版 V3.0(神秘版本)》详细图文教程:安装、存档继承与玩法解析
  • 在 Qt Creator 中使用 Promote 功能让 QTabWidget 显示自定义页面
  • AI赋能标准化流程:智能汽车软件CI/CT最佳实践新范式
  • The 2023 ICPC Asia Shenyang Regional Contest K. Maximum Rating
  • 用积木思维搞定TCP/IP——LuatOS快速上手指南
  • 2025 年江门办公室装修公司最新推荐排行榜:助力企业避开装修陷阱,精选优质服务品牌
  • WPF自动弹出软件键盘
  • 【碎片化学习】JMeter中常用的设置优化
  • win10系统以太网未识别网络 没有有效ip配置怎么办?
  • 怎么考PostgreSQL PG中级认证证书
  • 大学本科及研究生金融专业题库数据集:109157条高质量中文金融教育题库数据,涵盖银行证券保险投资理财等全领域,支持智能教育系统与机器学习算法训练的专业数据集
  • 【比赛记录】2025CSP-S模拟赛61
  • 基于Rokid CXR-S SDK的智能AR翻译助手技术拆解与实现指南
  • VRED 2025:专业三维可视化与虚拟现实领域的高效设计工具
  • 2025年办公与商业空间软膜天花系统推荐榜:办公室/酒店/展厅/商场/汽车4S店软膜天花厂家,专注光环境与装饰一体化解决方案
  • SZMS 251009 订题赛 题解
  • Debian 12安装docker的正确方法
  • 【流量网关】k8s与apisix统一的流量入口方案(内网版)
  • 基于STM32F4系列MCU和CS5530 24位SDADC的称重传感器系统实现
  • 2025 年环保板材厂家最新推荐榜:硬包板 / 竹木纤维板等全品类 企业深度解析
  • kong 网关下集成 Consul服务注册与发现
  • cad圆滑连接两段线:blend
  • 在 gitea 服务器端查询 lfs 文件占用情况
  • HDR图像生成算法详解
  • Introduction: Why Optimization?
  • 基于MATLAB的二自由度机械臂PID控制仿真
  • Spring AOP原理
  • Ventoy引导Kali live USB持久化