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的Flask框架中实现简单的登录功能的教程
Apr 20 Python
python下paramiko模块实现ssh连接登录Linux服务器
Jun 03 Python
Python的网络编程库Gevent的安装及使用技巧
Jun 24 Python
Python类的动态修改的实例方法
Mar 24 Python
Python实现按学生年龄排序的实际问题详解
Aug 29 Python
Python实现App自动签到领取积分功能
Sep 29 Python
Python多项式回归的实现方法
Mar 11 Python
使用opencv将视频帧转成图片输出
Dec 10 Python
pytorch:model.train和model.eval用法及区别详解
Feb 20 Python
Tensorflow--取tensorf指定列的操作方式
Jun 30 Python
通过案例解析python鸭子类型相关原理
Oct 10 Python
python基础入门之字典和集合
Jun 13 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
磨咖啡豆的密诀
2021/03/03 冲泡冲煮
php,ajax实现分页
2008/03/27 PHP
Php中使用Select 查询语句的实例
2014/02/19 PHP
PHP闭包定义与使用简单示例
2018/04/13 PHP
Javascript模板技术
2007/04/27 Javascript
基于jquery的禁用右键、文本选择功能、复制按键的实现代码
2013/08/27 Javascript
探究Javascript模板引擎mustache.js使用方法
2016/01/26 Javascript
用window.onerror捕获并上报Js错误的方法
2016/01/27 Javascript
BootStrapValidator校验方式
2016/12/19 Javascript
JS多文件上传的实例代码
2017/01/11 Javascript
前端编码规范(3)JavaScript 开发规范
2017/01/21 Javascript
ES6中Symbol类型用法实例详解
2017/04/06 Javascript
vue-content-loader内容加载器的使用方法
2018/08/05 Javascript
jQuery仿移动端支付宝键盘的实现代码
2018/08/15 jQuery
vue弹窗插件实战代码
2018/09/08 Javascript
js实现简易计算器功能
2019/10/18 Javascript
JS倒计时两种实现方式代码实例
2020/07/27 Javascript
Vuex实现简单购物车
2021/01/10 Vue.js
python查找第k小元素代码分享
2013/12/18 Python
python实现在目录中查找指定文件的方法
2014/11/11 Python
利用python实现命令行有道词典的方法示例
2017/01/31 Python
深入理解Python 关于supper 的 用法和原理
2018/02/28 Python
python中ASCII码字符与int之间的转换方法
2018/07/09 Python
python3 flask实现文件上传功能
2020/03/20 Python
谈谈Python中的while循环语句
2019/03/10 Python
我就是这样学习Python中的列表
2019/06/02 Python
python调用HEG工具批量处理MODIS数据的方法及注意事项
2020/02/18 Python
Python内建序列通用操作6种实现方法
2020/03/26 Python
python3通过udp实现组播数据的发送和接收操作
2020/05/05 Python
英国专业美容产品在线:Mylee(从指甲到脱毛)
2020/07/06 全球购物
电气自动化大学生求职信
2013/10/16 职场文书
五一手机促销方案
2014/03/08 职场文书
工资收入证明
2014/10/07 职场文书
2014年环卫工作总结
2014/11/22 职场文书
WCG2010 星际争霸决赛 Flash vs Goojila 1 星际经典比赛回顾
2022/04/01 星际争霸
table设置超出部分隐藏,鼠标移上去显示全部内容的方法
2022/12/24 HTML / CSS