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 相关文章推荐
简单介绍Python2.x版本中的cmp()方法的使用
May 20 Python
Python3.6正式版新特性预览
Dec 15 Python
Python使用QRCode模块生成二维码实例详解
Jun 14 Python
初学python的操作难点总结(新手必看篇)
Aug 03 Python
python 类对象和实例对象动态添加方法(分享)
Dec 31 Python
浅谈Tensorflow模型的保存与恢复加载
Apr 26 Python
Django 在iframe里跳转顶层url的例子
Aug 21 Python
浅谈PyQt5中异步刷新UI和Python多线程总结
Dec 13 Python
Python 日期的转换及计算的具体使用详解
Jan 16 Python
浅谈Tensorflow 动态双向RNN的输出问题
Jan 20 Python
Python3打包exe代码2种方法实例解析
Feb 17 Python
Django使用django-simple-captcha做验证码的实现示例
Jan 07 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操作xml代码
2010/06/17 PHP
关于php连接mssql:pdo odbc sql server
2011/07/20 PHP
PHP三元运算符的结合性介绍
2012/01/10 PHP
PHP模板引擎Smarty内建函数section,sectionelse用法详解
2016/04/11 PHP
php实现session共享的实例方法
2019/09/19 PHP
PHP使用gearman进行异步的邮件或短信发送操作详解
2020/02/27 PHP
改善用户体验的五款jQuery插件分享
2011/05/22 Javascript
验证码在IE中不刷新而谷歌等浏览器正常的解决方案
2014/03/18 Javascript
JS实现控制表格单元格垂直对齐的方法
2015/03/30 Javascript
JS实现跟随鼠标的链接文字提示框效果
2015/08/06 Javascript
RequireJS多页面应用实例分析
2016/06/29 Javascript
NodeJS安装图文教程
2018/04/19 NodeJs
微信 jssdk 签名错误invalid signature的解决方法
2019/01/14 Javascript
JavaScript实现美化滑块效果
2019/05/17 Javascript
JavaScript实现Tab选项卡切换
2020/02/13 Javascript
JavaScript仿京东轮播图效果
2021/02/25 Javascript
[44:47]Ti4 循环赛第三日 iG vs NaVi
2014/07/12 DOTA
[00:36]DOTA2上海特级锦标赛 Alliance战队宣传片
2016/03/04 DOTA
python测试驱动开发实例
2014/10/08 Python
浅析Python中元祖、列表和字典的区别
2016/08/17 Python
Flask框架信号用法实例分析
2018/07/24 Python
django的settings中设置中文支持的实现
2019/04/28 Python
Django框架视图介绍与使用详解
2019/07/18 Python
使用Tensorflow将自己的数据分割成batch训练实例
2020/01/20 Python
Python bytes string相互转换过程解析
2020/03/05 Python
CSS3制作hover下划线动画
2017/03/27 HTML / CSS
用html5的canvas和JavaScript创建一个绘图程序的简单实例
2016/07/06 HTML / CSS
乡镇纠风工作实施方案
2014/03/22 职场文书
《草原的早晨》教学反思
2014/04/08 职场文书
捐款倡议书
2014/04/14 职场文书
产品发布会策划方案
2014/05/12 职场文书
机械专业技术员求职信
2014/06/14 职场文书
2015年精神文明建设工作总结
2015/04/21 职场文书
详解JavaScript中Arguments对象用途
2021/08/30 Javascript
一次线上mongo慢查询问题排查处理记录
2022/03/18 MongoDB
英国数字版游戏销量周榜公布 《小缇娜的奇幻之地》登顶
2022/04/03 其他游戏