Python如何创建装饰器时保留函数元信息


Posted in Python onAugust 07, 2020

问题

你写了一个装饰器作用在某个函数上,但是这个函数的重要的元信息比如名字、文档字符串、注解和参数签名都丢失了。

解决方案

任何时候你定义装饰器的时候,都应该使用 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__ 属性访问到函数签名信息。

以上就是Python如何创建装饰器时保留函数元信息的详细内容,更多关于Python保留函数元信息的资料请关注三水点靠木其它相关文章!

Python 相关文章推荐
phpsir 开发 一个检测百度关键字网站排名的python 程序
Sep 17 Python
Python类属性的延迟计算
Oct 22 Python
Python实现识别手写数字 Python图片读入与处理
Mar 23 Python
对python 矩阵转置transpose的实例讲解
Apr 17 Python
Python3.6简单反射操作示例
Jun 14 Python
Python实现自定义函数的5种常见形式分析
Jun 16 Python
PyCharm更改字体和界面样式的方法步骤
Sep 27 Python
使用sklearn的cross_val_score进行交叉验证实例
Feb 28 Python
解决python父线程关闭后子线程不关闭问题
Apr 25 Python
Python使用socketServer包搭建简易服务器过程详解
Jun 12 Python
python3.7.3版本和django2.2.3版本是否可以兼容
Sep 01 Python
Django mysqlclient安装和使用详解
Sep 17 Python
python的launcher用法知识点总结
Aug 07 #Python
详解PyQt5中textBrowser显示print语句输出的简单方法
Aug 07 #Python
PyQt5的相对布局管理的实现
Aug 07 #Python
详解pyqt5的UI中嵌入matplotlib图形并实时刷新(挖坑和填坑)
Aug 07 #Python
Python configparser模块封装及构造配置文件
Aug 07 #Python
Python logging模块进行封装实现原理解析
Aug 07 #Python
Python定时任务APScheduler安装及使用解析
Aug 07 #Python
You might like
DOTA2 6.87版本后新眼位详解攻略
2020/04/20 DOTA
让你的WINDOWS同时支持MYSQL4,MYSQL4.1,MYSQL5X
2006/12/06 PHP
在VS2008中编译MYSQL5.1.48的方法
2010/07/03 PHP
让php处理图片变得简单 基于gb库的图片处理类附实例代码下载
2011/05/17 PHP
php Rename 更改文件、文件夹名称
2011/05/24 PHP
PHP内核介绍及扩展开发指南―基础知识
2011/09/11 PHP
php mail to 配置详解
2014/01/16 PHP
ThinkPHP的常用配置选项汇总
2016/03/24 PHP
php遍历解析xml字符串的方法
2016/05/05 PHP
yum命令安装php7和相关扩展
2016/07/04 PHP
php使用CutyCapt实现网页截图保存的方法
2016/10/03 PHP
一个网页标题title的闪动提示效果实现思路
2014/03/22 Javascript
JQuery查找DOM节点的方法
2015/06/11 Javascript
js实现简单的获取验证码按钮效果
2017/03/03 Javascript
angularjs+bootstrap菜单的使用示例代码
2017/03/07 Javascript
Vuejs仿网易云音乐实现听歌及搜索功能
2017/03/30 Javascript
javascript高级模块化require.js的具体使用方法
2017/10/31 Javascript
JS中的JSON对象的定义和取值实现代码
2018/05/09 Javascript
微信小程序异步API为Promise简化异步编程的操作方法
2018/08/14 Javascript
如何实现一个webpack模块解析器
2018/10/24 Javascript
详解js创建对象的几种方法及继承
2019/04/12 Javascript
使用Angular material主题定义自己的组件库的配色体系
2019/09/04 Javascript
Python实现批量修改文件名实例
2015/07/08 Python
快速了解Python相对导入
2018/01/12 Python
Django的HttpRequest和HttpResponse对象详解
2018/01/26 Python
Python使用pickle模块实现序列化功能示例
2018/07/13 Python
pytorch 在sequential中使用view来reshape的例子
2019/08/20 Python
Python脚本破解压缩文件口令实例教程(zipfile)
2020/06/14 Python
HTML5中的Scoped属性使用实例
2014/04/23 HTML / CSS
Jo Malone美国官网:祖玛珑香水
2017/03/27 全球购物
法学专业本科生自荐信范文
2013/12/17 职场文书
大学四年职业生涯规划书范文
2014/01/02 职场文书
危货运输企业安全生产责任书
2014/07/28 职场文书
提档介绍信范文
2015/10/22 职场文书
2016年母亲节寄语
2015/12/04 职场文书
2016年优秀党员教师先进事迹材料
2016/02/29 职场文书