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格式化css文件的方法
Mar 10 Python
浅析python实现scrapy定时执行爬虫
Mar 04 Python
Python使用pickle模块储存对象操作示例
Aug 15 Python
python将秒数转化为时间格式的实例
Sep 16 Python
python使用循环打印所有三位数水仙花数的实例
Nov 13 Python
python2和python3的输入和输出区别介绍
Nov 20 Python
Python实现html转换为pdf报告(生成pdf报告)功能示例
May 04 Python
python实现邮件自动发送
Aug 10 Python
Python urlencode和unquote函数使用实例解析
Mar 31 Python
python thrift 实现 单端口多服务的过程
Jun 08 Python
python爬虫爬取网页数据并解析数据
Sep 18 Python
windows下python 3.9 Numpy scipy和matlabplot的安装教程详解
Nov 28 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 学习提高路线分享
2011/10/23 PHP
Thinkphp模板中截取字符串函数简介
2014/06/17 PHP
php读取txt文件并将数据插入到数据库
2016/02/23 PHP
微信公众号开发之通过接口删除菜单
2017/02/20 PHP
PHP中有关长整数的一些操作教程
2019/09/11 PHP
PHP7 错误处理机制修改
2021/03/09 PHP
做网页的一些技巧
2007/02/01 Javascript
Prototype 工具函数 学习
2009/07/23 Javascript
js获取html参数及向swf传递参数应用介绍
2013/02/18 Javascript
eclipse如何忽略js文件报错(附图)
2013/10/30 Javascript
使用jquery实现IE下按backspace相当于返回操作
2014/03/18 Javascript
jQuery中DOM操作实例分析
2015/01/23 Javascript
Bootstrap每天必学之下拉菜单
2015/11/25 Javascript
jQuery使用zTree插件实现树形菜单和异步加载
2016/02/25 Javascript
JavaScript里 ==与===区别详解
2016/08/16 Javascript
JS实现六边形3D拖拽翻转效果的方法
2016/09/11 Javascript
ExtJs的Ext.Ajax.request实现waitMsg等待提示效果
2017/06/14 Javascript
React如何利用相对于根目录进行引用组件详解
2017/10/09 Javascript
关于vue面试题汇总
2018/03/20 Javascript
使用vuex缓存数据并优化自己的vuex-cache
2018/05/30 Javascript
elementui实现预览图片组件二次封装
2020/12/29 Javascript
python笔记(2)
2012/10/24 Python
探寻python多线程ctrl+c退出问题解决方案
2014/10/23 Python
关于pip的安装,更新,卸载模块以及使用方法(详解)
2017/05/19 Python
python学习教程之Numpy和Pandas的使用
2017/09/11 Python
python实现拓扑排序的基本教程
2018/03/11 Python
对python GUI实现完美进度条的示例详解
2018/12/13 Python
关于Python 的简单栅格图像边界提取方法
2019/07/05 Python
Python Numpy 控制台完全输出ndarray的实现
2020/02/19 Python
Pytorch转onnx、torchscript方式
2020/05/25 Python
编程实现当输入某产品代码则打印出该产品记录的功能
2014/05/03 面试题
实用求职信范文分享
2013/12/25 职场文书
文明学生标兵事迹
2014/01/21 职场文书
毕业论文答辩开场白和结束语
2015/05/27 职场文书
幼儿园中班教育随笔
2015/08/14 职场文书
【海涛DOTA解说】EVE女子战队独家录像加ZSMJ神牛两连发
2022/04/01 DOTA