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从零实现贝叶斯分类器的机器学习的教程
Mar 31 Python
python实现搜索本地文件信息写入文件的方法
Feb 22 Python
Python使用Pycrypto库进行RSA加密的方法详解
Jun 06 Python
Python字符编码判断方法分析
Jul 01 Python
python中如何使用正则表达式的非贪婪模式示例
Oct 09 Python
PyCharm 常用快捷键和设置方法
Dec 20 Python
python3的print()函数的用法图文讲解
Jul 16 Python
python网络编程socket实现服务端、客户端操作详解
Mar 24 Python
python实现最短路径的实例方法
Jul 19 Python
python实现二分查找算法
Sep 18 Python
一篇文章带你搞懂Python类的相关知识
May 20 Python
Python TypeError: ‘float‘ object is not subscriptable错误解决
Dec 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实现将上传word文件转为html的方法
2015/06/03 PHP
Zend Framework入门应用实例详解
2016/12/11 PHP
Prototype中dom对象方法汇总
2008/09/17 Javascript
JavaScript 无符号右移赋值操作
2009/04/17 Javascript
Jquery 基础学习笔记之文档处理
2009/05/29 Javascript
jQuery EasyUI API 中文文档 - PropertyGrid属性表格
2011/11/18 Javascript
Javascript数组的排序 sort()方法和reverse()方法
2012/06/04 Javascript
图片旋转、鼠标滚轮缩放、镜像、切换图片js代码
2020/12/13 Javascript
基于javascript实现根据身份证号码识别性别和年龄
2016/01/22 Javascript
基于BootStrap的图片轮播效果展示实例代码
2016/05/23 Javascript
原生js调用json方法总结
2018/02/22 Javascript
解决vue2.0动态绑定图片src属性值初始化时报错的问题
2018/03/14 Javascript
解决npm管理员身份install时出现权限的问题
2018/03/16 Javascript
基于js中的存储键值对以及注意事项介绍
2018/03/30 Javascript
vue自定义指令的创建和使用方法实例分析
2018/12/04 Javascript
[02:54]DOTA2英雄基础教程 暗影牧师戴泽
2013/12/05 DOTA
在Python的Flask框架下使用sqlalchemy库的简单教程
2015/04/09 Python
python使用reportlab实现图片转换成pdf的方法
2015/05/22 Python
Python实现SVN的目录周期性备份实例
2015/07/17 Python
对python-3-print重定向输出的几种方法总结
2018/05/11 Python
pygame游戏之旅 计算游戏中躲过的障碍数量
2018/11/20 Python
Python发送邮件测试报告操作实例详解
2018/12/08 Python
pyqt5实现登录界面的模板
2020/05/30 Python
matplotlib 多个图像共用一个colorbar的实现示例
2020/09/10 Python
python 生成器需注意的小问题
2020/09/29 Python
什么是数组名
2012/05/10 面试题
中职应届生会计求职信
2013/10/23 职场文书
英语教学随笔感言
2014/02/20 职场文书
生日礼品店创业计划书范文
2014/03/21 职场文书
社区服务活动小结
2014/07/08 职场文书
活动总结格式
2014/08/30 职场文书
机关驾驶员违规检讨书
2014/09/13 职场文书
民主评议党员登记表自我评价
2014/10/20 职场文书
2014年艾滋病防治工作总结
2014/12/10 职场文书
放假通知范文
2015/04/14 职场文书
军训通讯稿范文
2015/07/18 职场文书