Python 在函数上添加包装器


Posted in Python onJuly 28, 2020

问题

你想在函数上添加一个包装器,增加额外的操作处理(比如日志、计时等)。

解决方案

如果你想使用额外的代码包装一个函数,可以定义一个装饰器函数,例如:

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(10000000)
countdown 0.87188299392912
>>>

讨论

一个装饰器就是一个函数,它接受一个函数作为参数并返回一个新的函数。当你像下面这样写:

@timethis
def countdown(n):
  pass

跟像下面这样写其实效果是一样的:

def countdown(n):
  pass
countdown = timethis(countdown)

顺便说一下,内置的装饰器比如 @staticmethod, @classmethod,@property 原理也是一样的。例如,下面这两个代码片段是等价的:

class A:
  @classmethod
  def method(cls):
    pass

class B:
  # Equivalent definition of a class method
  def method(cls):
    pass
  method = classmethod(method)

在上面的 wrapper() 函数中,装饰器内部定义了一个使用 *args 和 **kwargs 来接受任意参数的函数。在这个函数里面调用了原始函数并将其结果返回,不过你还可以添加其他额外的代码(比如计时)。然后这个新的函数包装器被作为结果返回来代替原始函数。

需要强调的是装饰器并不会修改原始函数的参数签名以及返回值。使用 *args 和 **kwargs 目的就是确保任何参数都能适用。而返回结果值基本都是调用原始函数 func(*args, **kwargs) 的返回结果,其中func就是原始函数。

刚开始学习装饰器的时候,会使用一些简单的例子来说明,比如上面演示的这个。不过实际场景使用时,还是有一些细节问题要注意的。比如上面使用 @wraps(func) 注解是很重要的,它能保留原始函数的元数据(下一小节会讲到),新手经常会忽略这个细节。接下来的几个小节我们会更加深入的讲解装饰器函数的细节问题,如果你想构造你自己的装饰器函数,需要认真看一下。

以上就是Python 在函数上添加包装器的详细内容,更多关于Python 添加包装器的资料请关注三水点靠木其它相关文章!

Python 相关文章推荐
Python+Turtle动态绘制一棵树实例分享
Jan 16 Python
windows10下python3.5 pip3安装图文教程
Apr 02 Python
python 实现在Excel末尾增加新行
May 02 Python
Python解析并读取PDF文件内容的方法
May 08 Python
python逆序打印各位数字的方法
Jun 25 Python
Python+pandas计算数据相关系数的实例
Jul 03 Python
Python中的groupby分组功能的实例代码
Jul 11 Python
python实现控制台打印的方法
Jan 12 Python
python实现简单加密解密机制
Mar 19 Python
用python实现监控视频人数统计
May 21 Python
python自动化操作之动态验证码、滑动验证码的降噪和识别
Aug 30 Python
python实现简单石头剪刀布游戏
Oct 24 Python
Python matplotlib图例放在外侧保存时显示不完整问题解决
Jul 28 #Python
Python 如何反方向迭代一个序列
Jul 28 #Python
Python Matplotlib简易教程(小白教程)
Jul 28 #Python
Python把图片转化为pdf代码实例
Jul 28 #Python
关于python3.7安装matplotlib始终无法成功的问题的解决
Jul 28 #Python
Python 合并拼接字符串的方法
Jul 28 #Python
Python reques接口测试框架实现代码
Jul 28 #Python
You might like
Php部分常见问题总结
2006/10/09 PHP
php通过文件头检测文件类型通用代码类(zip,rar等)
2010/10/19 PHP
PHP文章按日期(月日)SQL归档语句
2012/11/29 PHP
PHP处理Ajax请求与Ajax跨域问题
2017/02/13 PHP
js 弹出框只弹一次(二次修改之后的)
2013/11/26 Javascript
JQuery解析HTML、JSON和XML实例详解
2014/03/29 Javascript
jquery text()方法取标签中的文本
2014/07/25 Javascript
JavaScript实现多个重叠层点击切换效果的方法
2015/04/24 Javascript
使用AngularJS创建单页应用的编程指引
2015/06/19 Javascript
浅谈JavaScript中的字符编码转换问题
2015/07/07 Javascript
javascript仿京东导航左侧分类导航下拉菜单效果
2020/11/25 Javascript
JavaScript实现复制内容到粘贴板代码
2016/03/31 Javascript
jQuery 获取select选中值及清除选中状态
2016/12/13 Javascript
Vue中父组件向子组件通信的方法
2017/07/11 Javascript
vue富文本编辑器组件vue-quill-edit使用教程
2018/09/21 Javascript
10行代码实现微信小程序滑动tab切换
2018/12/28 Javascript
[01:03:38]2014 DOTA2国际邀请赛中国区预选赛5.21 CNB VS CIS
2014/05/22 DOTA
python实现将内容分行输出
2015/11/05 Python
Python3学习笔记之列表方法示例详解
2017/10/06 Python
python+pandas生成指定日期和重采样的方法
2018/04/11 Python
实例讲解Python爬取网页数据
2018/07/08 Python
Python中的groupby分组功能的实例代码
2018/07/11 Python
Python图像处理实现两幅图像合成一幅图像的方法【测试可用】
2019/01/04 Python
python实现windows壁纸定期更换功能
2019/01/21 Python
详解如何减少python内存的消耗
2019/08/09 Python
python GUI库图形界面开发之PyQt5信号与槽多窗口数据传递详细使用方法与实例
2020/03/08 Python
python实现AHP算法的方法实例(层次分析法)
2020/09/09 Python
Python实现手势识别
2020/10/21 Python
成人大专自我鉴定范文
2013/10/19 职场文书
小学标准化建设汇报材料
2014/08/16 职场文书
青年志愿者活动方案
2014/08/17 职场文书
2014年青年教师工作总结
2014/12/17 职场文书
2015年共青团工作总结
2015/05/15 职场文书
2015年乡镇党务公开工作总结
2015/05/19 职场文书
2016年社区服务活动总结
2016/04/06 职场文书
了解Redis常见应用场景
2021/06/23 Redis