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对两个有序列表进行合并和排序的例子
Jun 13 Python
把项目从Python2.x移植到Python3.x的经验总结
Apr 20 Python
Python中使用items()方法返回字典元素对的教程
May 21 Python
python正则分析nginx的访问日志
Jan 17 Python
Python使用内置json模块解析json格式数据的方法
Jul 20 Python
python使用pycharm环境调用opencv库
Feb 11 Python
python判断数字是否是超级素数幂
Sep 27 Python
在PyCharm中三步完成PyPy解释器的配置的方法
Oct 29 Python
Python编程深度学习计算库之numpy
Dec 28 Python
Python读取stdin方法实例
May 24 Python
使用 python pyautogui实现鼠标键盘控制功能
Aug 04 Python
Python+OpenCV实现实时眼动追踪的示例代码
Nov 11 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中比较简单的导入phpmyadmin生成的sql文件的方法
2011/06/28 PHP
PHP怎么实现网站保存快捷方式方便用户随时浏览
2013/08/15 PHP
PHP实现图片裁剪、添加水印效果代码
2014/10/01 PHP
php调用mysql存储过程实例分析
2014/12/29 PHP
微信 getAccessToken方法详解及实例
2016/11/23 PHP
js history对象简单实现返回和前进
2013/10/30 Javascript
jQuery实现自定义下拉列表
2015/01/05 Javascript
深入解析JavaScript中的立即执行函数
2016/05/21 Javascript
微信小程序 封装http请求实例详解
2017/01/16 Javascript
jquery实现提示语淡入效果
2017/05/05 jQuery
jstree单选功能的实现方法
2017/06/07 Javascript
前端构建工具之gulp的配置与搭建详解
2017/06/12 Javascript
vue中使用sessionStorage记住密码功能
2018/07/24 Javascript
vue项目中使用lib-flexible解决移动端适配的问题解决
2018/08/23 Javascript
Vue通过ref父子组件拿值方法
2018/09/12 Javascript
[02:56]DOTA2英雄基础教程 巨魔战将
2013/12/10 DOTA
python实现统计代码行数的方法
2015/05/22 Python
Python基于贪心算法解决背包问题示例
2017/11/27 Python
Python中使用logging和traceback模块记录日志和跟踪异常
2019/04/09 Python
python 检查数据中是否有缺失值,删除缺失值的方式
2019/12/02 Python
Python3 hashlib密码散列算法原理详解
2020/03/30 Python
Jupyter notebook无法导入第三方模块的解决方式
2020/04/15 Python
基于python模拟bfs和dfs代码实例
2020/11/19 Python
python中用ctypes模拟点击的实例讲解
2020/11/26 Python
CSS中垂直居中的简单实现方法
2015/07/06 HTML / CSS
Banana Republic英国官网:香蕉共和国,GAP集团旗下偏贵族风
2018/04/24 全球购物
内科护士实习自我鉴定
2013/10/17 职场文书
工程造价与管理专业应届生求职信
2013/11/23 职场文书
经济管理专业毕业生自荐信范文
2014/01/02 职场文书
珍珠奶茶店创业计划书
2014/01/11 职场文书
教师考核评语
2014/04/28 职场文书
放飞梦想演讲稿600字
2014/08/26 职场文书
2014年重阳节老干部座谈会上的讲话稿
2014/09/25 职场文书
2015年文明创建工作总结
2015/04/30 职场文书
家庭聚会祝酒词
2015/08/11 职场文书
PyQt5爬取12306车票信息程序的实现
2021/05/14 Python