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之有容乃大的list(3)
Sep 15 Python
浅谈python中的面向对象和类的基本语法
Jun 13 Python
Python内置函数OCT详解
Nov 09 Python
python构建深度神经网络(续)
Mar 10 Python
pytorch 更改预训练模型网络结构的方法
Aug 19 Python
在python image 中安装中文字体的实现方法
Aug 22 Python
tensorflow2.0与tensorflow1.0的性能区别介绍
Feb 07 Python
完美解决pycharm导入自己写的py文件爆红问题
Feb 12 Python
Python读取配置文件(config.ini)以及写入配置文件
Apr 08 Python
Python绘制全球疫情变化地图的实例代码
Apr 20 Python
PyQt5多线程防卡死和多窗口用法的实现
Sep 15 Python
Python编程根据字典列表相同键的值进行合并
Oct 05 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 discuz 主题表和回帖表的设计
2009/03/13 PHP
一个PHP并发访问实例代码
2012/09/06 PHP
慎用preg_replace危险的/e修饰符(一句话后门常用)
2013/06/19 PHP
ThinkPHP模板中判断volist循环的最后一条记录的验证方法
2014/07/01 PHP
laravel通过创建自定义artisan make命令来新建类文件详解
2017/08/17 PHP
jQuery学习笔记之jQuery动画效果
2013/09/09 Javascript
javascript处理表单示例(javascript提交表单)
2014/04/28 Javascript
AngularJS的内置过滤器详解
2015/05/14 Javascript
浅谈javascript的call()、apply()、bind()的用法
2016/02/21 Javascript
Javascript中的对象和原型(二)
2016/08/12 Javascript
js选项卡的制作方法
2017/01/23 Javascript
js实现登录框鼠标拖拽效果
2017/03/09 Javascript
jQuery实现Select下拉列表进行状态选择功能
2017/03/30 jQuery
yarn的使用与升级Node.js的方法详解
2017/06/04 Javascript
node中Express 动态设置端口的方法
2017/08/04 Javascript
elementui的默认样式修改方法
2018/02/23 Javascript
vue.js实现会动的简历(包含底部导航功能,编辑功能)
2019/04/08 Javascript
Vue编写可显示周和月模式的日历 Vue自定义日历内容的显示
2019/06/26 Javascript
JavaScript实现下拉列表
2021/01/20 Javascript
介绍Python中内置的itertools模块
2015/04/29 Python
在Python程序员面试中被问的最多的10道题
2017/12/05 Python
python hook监听事件详解
2018/10/25 Python
pygame实现贪吃蛇游戏(下)
2019/10/29 Python
Python hmac模块使用实例解析
2019/12/24 Python
解析Tensorflow之MNIST的使用
2020/06/30 Python
python实现数字炸弹游戏程序
2020/07/17 Python
稀有和绝版书籍:Biblio.com
2017/02/02 全球购物
升职自荐信范文
2013/10/05 职场文书
目标责任书范本
2014/04/16 职场文书
2015年党员个人自我评价
2015/03/03 职场文书
老乡聚会通知
2015/04/23 职场文书
功夫熊猫观后感
2015/06/10 职场文书
golang中实现给gif、png、jpeg图片添加文字水印
2021/04/26 Golang
Django集成富文本编辑器summernote的实现步骤
2021/05/31 Python
解决Mysql的left join无效及使用的注意事项说明
2021/07/01 MySQL
Elasticsearch 索引操作和增删改查
2022/04/19 Python