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 ORM框架SQLAlchemy学习笔记之安装和简单查询实例
Jun 10 Python
Python 爬虫之超链接 url中含有中文出错及解决办法
Aug 03 Python
Scrapy的简单使用教程
Oct 24 Python
python之django母板页面的使用
Jul 03 Python
对DataFrame数据中的重复行,利用groupby累加合并的方法详解
Jan 30 Python
python+django+rest框架配置创建方法
Aug 31 Python
解决python cv2.imread 读取中文路径的图片返回为None的问题
Jun 02 Python
next在python中返回迭代器的实例方法
Dec 15 Python
详解python中的异常和文件读写
Jan 03 Python
pytorch 计算Parameter和FLOP的操作
Mar 04 Python
Django路由层如何获取正确的url
Jul 15 Python
Pandas-DataFrame知识点汇总
Mar 16 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导出到Excel或CSV的详解(附utf8、gbk 编码转换)
2013/06/25 PHP
PHP网页游戏学习之Xnova(ogame)源码解读(十六)
2014/06/30 PHP
destoon实现首页显示供应、企业、资讯条数的方法
2014/07/15 PHP
PHP中ini_set与ini_get用法实例
2014/11/04 PHP
php生成图片验证码-附五种验证码
2015/08/19 PHP
PHP使用curl函数发送Post请求的注意事项
2016/11/26 PHP
PHP常见数组排序方法小结
2018/08/20 PHP
Laravel获取当前请求的控制器和方法以及中间件的例子
2019/10/11 PHP
js调试系列 控制台命令行API使用方法
2014/06/18 Javascript
深入分析原生JavaScript事件
2014/12/29 Javascript
JQuery创建DOM节点的方法
2015/06/11 Javascript
javascript页面倒计时实例
2015/07/25 Javascript
jquery实现点击弹出带标题栏的弹出层(从右上角飞入)效果
2015/09/19 Javascript
详解javascript中原始数据类型Null和Undefined
2015/12/17 Javascript
Ajax分页插件Pagination从前台jQuery到后端java总结
2016/07/22 Javascript
jQuery对checkbox 复选框的全选全不选反选的操作
2016/08/09 Javascript
利用BootStrap弹出二级对话框的简单实现方法
2016/09/21 Javascript
Angular2学习笔记——详解NgModule模块
2016/12/02 Javascript
ReactNative页面跳转Navigator实现的示例代码
2017/08/02 Javascript
Vue配合iView实现省市二级联动的示例代码
2018/07/27 Javascript
js+canvas实现五子棋小游戏
2020/08/02 Javascript
微信小程序实现简单购物车功能
2020/12/30 Javascript
用Python实现通过哈希算法检测图片重复的教程
2015/04/02 Python
Python的Flask框架与数据库连接的教程
2015/04/20 Python
Python使用Paramiko模块编写脚本进行远程服务器操作
2016/05/05 Python
Python使用pylab库实现画线功能的方法详解
2017/06/08 Python
利用Pytorch实现简单的线性回归算法
2020/01/15 Python
Python判断远程服务器上Excel文件是否被人打开的方法
2020/07/13 Python
Python3爬虫关于识别检验滑动验证码的实例
2020/07/30 Python
Sneaker Studio捷克:购买运动鞋
2018/07/08 全球购物
C#笔试题
2015/07/14 面试题
反腐倡廉警示教育活动总结
2014/05/05 职场文书
需求分析说明书
2014/05/09 职场文书
教师远程研修感悟
2015/11/18 职场文书
Python语言中的数据类型-序列
2022/02/24 Python
如何开启Apache,Nginx和IIS服务器的GZIP压缩功能
2022/04/29 Servers