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中装饰器的一个妙用
Feb 08 Python
Python随机生成彩票号码的方法
Mar 05 Python
Python实现的生成格雷码功能示例
Jan 24 Python
python逐行读写txt文件的实例讲解
Apr 03 Python
python 执行文件时额外参数获取的实例
Dec 18 Python
python运行时强制刷新缓冲区的方法
Jan 14 Python
Python中的正则表达式与JSON数据交换格式
Jul 03 Python
Python 线程池用法简单示例
Oct 02 Python
nginx+uwsgi+django环境搭建的方法步骤
Nov 25 Python
Python自动采集微信联系人的实现示例
Feb 28 Python
python pandas dataframe 去重函数的具体使用
Jul 20 Python
python SOCKET编程基础入门
Feb 27 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获取mysql数据库中的所有表名的代码
2011/04/23 PHP
JS异常处理try..catch语句的作用和实例
2014/05/05 PHP
PHP指定截取字符串中的中英文或数字字符的实例分享
2016/03/18 PHP
基于Swoole实现PHP与websocket聊天室
2016/08/03 PHP
php+js实现点赞功能的示例详解
2020/08/07 PHP
Extjs Ajax 乱码问题解决方案
2009/04/15 Javascript
jQuery中的bind绑定事件与文本框改变事件的临时解决方法
2010/08/13 Javascript
正则表达式搭配js轻松处理json文本方便而老古
2013/02/17 Javascript
jQuery setTimeout传递字符串参数报错的解决方法
2014/06/09 Javascript
jQuery实现下拉菜单(内容为时间)的实时更新及图表的随动更新的方法
2016/07/07 Javascript
jQuery实现的无限级下拉菜单功能示例
2016/09/12 Javascript
探索Vue.js component内容实现
2016/11/03 Javascript
EditPlus中的正则表达式 实战(4)
2016/12/15 Javascript
js eval函数使用,js对象和字符串互转实例
2017/03/06 Javascript
webpack教程之webpack.config.js配置文件
2017/07/05 Javascript
使用JavaScript实现alert的实例代码
2017/07/06 Javascript
JS实现颜色的10进制转化成rgba格式的方法
2017/09/04 Javascript
JS函数本身的作用域实例分析
2020/03/16 Javascript
vue组件暴露和.js文件暴露接口操作
2020/08/11 Javascript
基于vue实现简易打地鼠游戏
2020/08/21 Javascript
[01:07:11]Secret vs Newbee 2019国际邀请赛小组赛 BO2 第二场 8.15
2019/08/17 DOTA
[45:59]完美世界DOTA2联赛PWL S2 FTD vs GXR 第二场 11.22
2020/11/24 DOTA
12步教你理解Python装饰器
2016/02/25 Python
python检测文件夹变化,并拷贝有更新的文件到对应目录的方法
2018/10/17 Python
详解python使用turtle库来画一朵花
2019/03/21 Python
解决python彩色螺旋线绘制引发的问题
2019/11/23 Python
如何通过python实现人脸识别验证
2020/01/17 Python
python中封包建立过程实例
2021/02/18 Python
Mio Skincare英国官网:身体紧致及孕期身体护理
2018/08/19 全球购物
英国工作场所设备购买网站:Slingsby
2019/05/03 全球购物
如何处理简单的PHP错误
2015/10/14 面试题
公务员平时考核实施方案
2014/03/11 职场文书
入党积极分子批评与自我批评思想汇报
2014/09/14 职场文书
党的群众路线教育实践活动整改方案
2014/10/28 职场文书
Python使用openpyxl批量处理数据
2021/06/23 Python
python游戏开发之pygame实现接球小游戏
2022/04/22 Python