Python如何创建装饰器时保留函数元信息
作者:D 发布时间:2023-03-29 12:32:46
标签:Python,装饰器,函数
问题
你写了一个装饰器作用在某个函数上,但是这个函数的重要的元信息比如名字、文档字符串、注解和参数签名都丢失了。
解决方案
任何时候你定义装饰器的时候,都应该使用 functools 库中的 @wraps 装饰器来注解底层包装函数。例如:
import time
from functools import wraps
def timethis(func):
'''
Decorator that reports the execution time.
'''
@wraps(func)
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print(func.__name__, end-start)
return result
return wrapper
下面我们使用这个被包装后的函数并检查它的元信息:
>>> @timethis
... def countdown(n):
... '''
... Counts down
... '''
... while n > 0:
... n -= 1
...
>>> countdown(100000)
countdown 0.008917808532714844
>>> countdown.__name__
'countdown'
>>> countdown.__doc__
'\n\tCounts down\n\t'
>>> countdown.__annotations__
{'n': <class 'int'>}
>>>
讨论
在编写装饰器的时候复制元信息是一个非常重要的部分。如果你忘记了使用 @wraps
, 那么你会发现被装饰函数丢失了所有有用的信息。比如如果忽略 @wraps
后的效果是下面这样的:
>>> countdown.__name__
'wrapper'
>>> countdown.__doc__
>>> countdown.__annotations__
{}
>>>
@wraps 有一个重要特征是它能让你通过属性 __wrapped__ 直接访问被包装函数。例如:
>>> countdown.__wrapped__(100000)
>>>
__wrapped__ 属性还能让被装饰函数正确暴露底层的参数签名信息。例如:
>>> from inspect import signature
>>> print(signature(countdown))
(n:int)
>>>
一个很普遍的问题是怎样让装饰器去直接复制原始函数的参数签名信息, 如果想自己手动实现的话需要做大量的工作,最好就简单的使用 @wraps
装饰器。 通过底层的 __wrapped__
属性访问到函数签名信息。
来源:https://python3-cookbook.readthedocs.io/zh_CN/latest/c09/p02_preserve_function_metadata_when_write_decorators.html


猜你喜欢
- 上文我们总结过了Python多继承的相关知识,没看过的小伙伴们也可以去看看,今天给大家介绍Python类的单继承相关知识。一、类的继承面向对
- 首先说明一点,每天的访问量并不大每天才2W的访问量,按道理说,访问量再增加一倍这样的服务器也应该足以承受。可是我们的服务器为什么总是这样频频
- 前言编程是一件很快乐的事,实现一个目的,我们可以有很多方法路径,在这篇文章我们介绍一些JavaScript的奇技淫巧,仅供大家参考,各路大神
- 1、linux系统一般自带perl可运行程序在:/usr/bin/perl2、perl测试程序#!/usr/bin/perl -wuse w
- 本文实例讲述了python修改操作系统时间的方法。分享给大家供大家参考。具体实现方法如下:#-*- coding:utf-8 -*-impo
- 有的时候需要手里的音频文件变速听,或可能变慢或可能变快这里使用的python进行操作,我的目标是将文件转成2倍速首先需要安装插件pip in
- 因为我们现在的前端框架做性能优化,为了找到各个组件及框架的具体解析耗时,需要在框架中嵌入一个耗时测试工具,性能测试跟不同的计算机硬件配置有很
- 环境:RHEL 5.4 x86 , oracle 11.2 1.设定环境变量 在/home/oracle编辑 # .bash_profile
- Array.prototype中定义了很多操作数组的方法,下面介绍ECMAScript3中的一些方法1.Array.join()方法该方法将
- 简介Part1:写在最前 OneProxy平民软件完全自主开发的分布式数据访问层,帮助用户在MySQL/
- 在上一篇博客中,我们学习了python遗传算法包geatpy。并用它展示了一个不带约束的单目标规划问题,对往期内容感兴趣的同学可以参考👇:链
- 方法一: 名称:DTS(这个在MSSQL2000里边也有)操作:在命令提示符窗口中运行 DTSWizard.exeSQL Server 导入
- 前言众所周知vue中使用路由的方式设置url参数,但是这种方式必须要在路径中附带参数,而且这个参数是需要在vue的路由中提前设置好的。相对来
- 一、引 言 在速度上,静态页面要比动态页面的比方php快很多,这是毫无疑问的,但是由于静态页面的灵活性较差,如果不借助数据库或其他的设备保存
- python 里面与时间有关的模块主要是 time 和 datetime如果想获取系统当前时间戳:time.time(),是一个float型
- 本文实例讲述了python使用正则表达式分析网页中的图片并进行替换的方法。分享给大家供大家参考。具体分析如下:这段代码分析网页中的所有图片表
- degrees()方法从弧度转换到度角x语法以下是degrees()方法的语法:degrees(x)注意:此函数是无法直接访问的
- 脚本如下: drop table table1; CREATE TABLE `andrew`.`table1` ( `name` VARCH
- 1、新建独立运行环境,命名为env[root@vultr ~]# mkdir projects # 测试的项目总目录[root@vultr
- 前言发现自己学习python 的各种库老是容易忘记,所有想利用这个平台,记录和分享一下学习时候的知识点,以后也能及时的复习,最近学习pand