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 相关文章推荐
python下函数参数的传递(参数带星号的说明)
Sep 19 Python
python开发之基于thread线程搜索本地文件的方法
Nov 11 Python
对python中array.sum(axis=?)的用法介绍
Jun 28 Python
Python实现的简单排列组合算法示例
Jul 04 Python
Python中遍历列表的方法总结
Jun 27 Python
PyTorch的深度学习入门之PyTorch安装和配置
Jun 27 Python
Django之PopUp的具体实现方法
Aug 31 Python
Python random库使用方法及异常处理方案
Mar 02 Python
python中shell执行知识点
May 06 Python
python数据类型强制转换实例详解
Jun 22 Python
selenium.webdriver中add_argument方法常用参数表
Apr 08 Python
python_tkinter弹出对话框创建
Mar 20 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
php设计模式 Interpreter(解释器模式)
2011/06/26 PHP
关于编写性能高效的javascript事件的技术
2014/11/28 Javascript
5种处理js跨域问题方法汇总
2014/12/04 Javascript
javascript编写贪吃蛇游戏
2015/07/07 Javascript
JavaScript中的cacheStorage使用详解
2015/07/29 Javascript
JavaScript中的return语句简单介绍
2015/12/07 Javascript
不得不分享的JavaScript常用方法函数集(下)
2015/12/25 Javascript
Bootstrap+jfinal实现省市级联下拉菜单
2016/05/30 Javascript
js 连续赋值的简单实现
2016/06/13 Javascript
javascript入门之window对象【新手必看】
2016/11/22 Javascript
Bootstrap轮播图的使用和理解4
2016/12/14 Javascript
关于jQuery EasyUI 中刷新Tab选项卡后一个页面变形的解决方法
2017/03/02 Javascript
Vue2.0如何发布项目实战
2017/07/27 Javascript
js中apply和Math.max()函数的问题及区别介绍
2018/03/27 Javascript
layui 监听表格复选框选中值的方法
2018/08/15 Javascript
JavaScript函数柯里化实现原理及过程
2020/12/02 Javascript
python实现异步回调机制代码分享
2014/01/10 Python
python网络编程学习笔记(五):socket的一些补充
2014/06/09 Python
python将ip地址转换成整数的方法
2015/03/17 Python
Python读取视频的两种方法(imageio和cv2)
2018/04/15 Python
Python开发的十个小贴士和技巧及长常犯错误
2018/09/27 Python
python实现FTP循环上传文件
2020/03/20 Python
python模拟斗地主发牌
2020/04/22 Python
TensorFlow实现模型断点训练,checkpoint模型载入方式
2020/05/26 Python
python suds访问webservice服务实现
2020/06/26 Python
Python爬虫逆向分析某云音乐加密参数的实例分析
2020/12/04 Python
英国最大的笔记本电脑直销专家:Laptops Direct
2019/07/20 全球购物
衰败城市英国官网:Urban Decay英国
2020/04/29 全球购物
2015年党员干部承诺书
2015/01/21 职场文书
介绍长城的导游词
2015/01/30 职场文书
建议书范文
2015/02/05 职场文书
汽车销售员工作总结
2015/08/12 职场文书
五年级作文之想象作文
2019/10/30 职场文书
MYSQL数据库使用UTF-8中文编码乱码的解决办法
2021/05/26 MySQL
详解JVM系列之内存模型
2021/06/10 Javascript
苹果的回收机器人可以通过拆解iPhone获取大量的金和铜并外公布了环境保护最新进展
2022/04/21 数码科技