如何实现一个python函数装饰器(Decorator)


Posted in Python onOctober 12, 2020

装饰器本质上是一个 Python 函数或类,它可以让其他函数或类在不需要做任何代码修改的前提下增加额外功能,装饰器的返回值也是一个函数/类对象。它经常用于为已有函数/类添加记录日志、计时统计、性能测试等。

首先定义一个倒计时函数,这个函数的功能非常简单,就是把n从当前值减少到0。

def countdown(n):
 while n > 0:
  print('time' + str(n))
  n -= 1

print(countdown.__name__)

程序输出:

countdown

1.为函数增加一个日志装饰器

假设现在要增强countdown的功能,在函数调用前后自动打印日志,又不想修改函数自身的功能。这种在代码运行期间动态增加功能的方式,称之为装饰器(Decorator)。

能打印日志的decorator,可以定义如下:

def log(func):
  def wrapper(*args, **kw):
    print('call %s().' % func.__name__)
    return func(*args, **kw)
  return wrapper

然后我们借助Python的@语法,把decorator置于函数的定义处:

@log
def countdown(n):
 while n > 0:
  print('time:' + str(n))
  n -= 1

countdown(10)

程序输出:

call countdown().
time:10
time:9
time:8
time:7
time:6
time:5
time:4
time:3
time:2
time:1

但此时我们再打印函数的name:

print(countdown.__name__)

程序输出:

wrapper

我们发现函数的元数据信息变了,这显然不是我们想要的结果。

2. 在装饰器中拷贝元数据

为了把函数的元数据信息都保留下来,我们可以直接使用Python提供的functools库中的@wraps装饰器。

from functools import wraps

def log(func):
  @wraps(func)
  def wrapper(*args, **kw):
    print('call %s().' % func.__name__)
    return func(*args, **kw)
  return wrapper

@log
def countdown(n):
 while n > 0:
  print('time:' + str(n))
  n -= 1

print(countdown.__name__)

程序输出:

countdown

3.为函数增加一个计时装饰器

添加函数装饰器的方法已经讲清楚了,现在再实现一个完整的函数计时耗时装饰器。

import time
from functools import wraps

def TimeCost(func):
 @wraps(func)
 def wrapper(*arg, **kwargs):
  start = time.time()
  result = func(*args, **kwargs)
  end = time.time()
  print(func.__name__, end - start)
  return result
 return wrapper

@TimeCost
def countdown(n):
 while n > 0:
  print('time:' + str(n))
  n -= 1

countdown(10000)

函数输出:

('countdown', 0.0004801750183105469)

参考资料:

以上就是如何实现一个python函数装饰器(Decorator)的详细内容,更多关于python函数装饰器的资料请关注三水点靠木其它相关文章!

Python 相关文章推荐
浅谈python 里面的单下划线与双下划线的区别
Dec 01 Python
python实时监控cpu小工具
Jun 21 Python
Python实现的网页截图功能【PyQt4与selenium组件】
Jul 12 Python
Python 创建新文件时避免覆盖已有的同名文件的解决方法
Nov 16 Python
原生python实现knn分类算法
Oct 24 Python
Python模块的制作方法实例分析
Dec 21 Python
pytorch实现onehot编码转为普通label标签
Jan 02 Python
Pycharm调试程序技巧小结
Aug 08 Python
让你相见恨晚的十个Python骚操作
Nov 18 Python
Python 实现Mac 屏幕截图详解
Oct 05 Python
Python实现日志实时监测的示例详解
Apr 06 Python
Python+pyaudio实现音频控制示例详解
Jul 23 Python
Vs Code中8个好用的python 扩展插件
Oct 12 #Python
Django中和时区相关的安全问题详解
Oct 12 #Python
python调用有道智云API实现文件批量翻译
Oct 10 #Python
python线程池 ThreadPoolExecutor 的用法示例
Oct 10 #Python
python开发一款翻译工具
Oct 10 #Python
Python pickle模块常用方法代码实例
Oct 10 #Python
Python3.9新特性详解
Oct 10 #Python
You might like
php 全局变量范围分析
2009/08/07 PHP
PHP imagecreatefrombmp 从BMP文件或URL新建一图像
2012/07/16 PHP
php调用nginx的mod_zip模块打包ZIP文件
2014/06/11 PHP
destoon调用discuz论坛中带图片帖子的实现方法
2014/08/21 PHP
PHP滚动日志的代码实现
2015/06/10 PHP
PHP全局变量与超级全局变量区别分析
2016/04/01 PHP
PHP对象链式操作实现原理分析
2016/10/09 PHP
JQuery的一些小应用收集
2010/03/27 Javascript
js检查页面上有无重复id的实现代码
2013/07/17 Javascript
jQuery调用WebMethod(PageMethod) NET2.0的方法
2016/04/15 Javascript
微信小程序wx:for和wx:for-item的用法详解
2018/04/01 Javascript
vue、react等单页面项目部署到服务器的方法及vue和react的区别
2018/09/29 Javascript
在JS循环中使用async/await的方法
2018/10/12 Javascript
微信小程序实现获取准确的腾讯定位地址功能示例
2019/03/27 Javascript
通过实践编写优雅的JavaScript代码
2019/05/30 Javascript
layer页面跳转,获取html子节点元素的值方法
2019/09/27 Javascript
Vue-router编程式导航的两种实现代码
2021/03/04 Vue.js
python获取指定网页上所有超链接的方法
2015/04/04 Python
解析Python编程中的包结构
2015/10/25 Python
Python3实现对列表按元组指定列进行排序的方法分析
2018/12/22 Python
python TF-IDF算法实现文本关键词提取
2019/05/29 Python
Python3实现发送邮件和发送短信验证码功能
2020/01/07 Python
python numpy实现多次循环读取文件 等间隔过滤数据示例
2020/03/14 Python
Python APScheduler执行使用方法详解
2020/12/10 Python
一款纯css3实现的漂亮的404页面的实例教程
2014/11/27 HTML / CSS
css3动画效果小结(推荐)
2016/07/25 HTML / CSS
Crucial英睿达法国官网:内存条及SSD固态硬盘升级
2018/07/13 全球购物
迪奥官网:Dior.com
2018/12/04 全球购物
入党积极分子介绍信
2014/01/17 职场文书
函授本科自我鉴定
2014/02/04 职场文书
离婚协议书范本样本
2014/08/19 职场文书
2014年英语教学工作总结
2014/12/17 职场文书
2015大学生党员自我评价范文
2015/03/03 职场文书
2015领导干部廉洁自律工作总结
2015/07/23 职场文书
2019年年中职场激励人心语录30条
2019/08/07 职场文书
如何使用注解方式实现 Redis 分布式锁
2022/07/23 Redis