如何实现一个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同时给两个收件人发送邮件的方法
Apr 30 Python
Python 常用的安装Module方式汇总
May 06 Python
Python跨文件全局变量的实现方法示例
Dec 10 Python
轻松实现TensorFlow微信跳一跳的AI
Jan 05 Python
Django添加favicon.ico图标的示例代码
Aug 07 Python
python3 中文乱码与默认编码格式设定方法
Oct 31 Python
Python实现高斯函数的三维显示方法
Dec 29 Python
基于python实现把json数据转换成Excel表格
May 07 Python
哪种Python框架适合你?简单介绍几种主流Python框架
Aug 04 Python
python实现人性化显示金额数字实例详解
Sep 25 Python
python中time包实例详解
Feb 02 Python
七个Python必备的GUI库
Apr 27 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
解析phpstorm + xdebug 远程断点调试
2013/06/20 PHP
PHP 解决session死锁的方法
2013/06/20 PHP
php异常处理方法实例汇总
2015/06/24 PHP
PC端微信扫码支付成功之后自动跳转php版代码
2017/07/07 PHP
php7 list()、session及其他模块的修改实例分析
2020/05/25 PHP
利用javascript移动div层-javascript 拖动层
2009/03/22 Javascript
js冒泡法和数组转换成字符串示例代码
2013/08/14 Javascript
调用DOM对象的focus使文本框获得焦点
2014/02/19 Javascript
js中document.write的那点事
2014/12/12 Javascript
Javascript中For In语句用法实例
2015/05/14 Javascript
jquery插件NProgress.js制作网页加载进度条
2015/06/05 Javascript
Vue.js父与子组件之间传参示例
2017/02/28 Javascript
使用D3.js创建物流地图的示例代码
2018/01/27 Javascript
详解js的视频和音频采集
2018/08/09 Javascript
angular2组件中定时刷新并清除定时器的实例讲解
2018/08/31 Javascript
js实现自动播放匀速轮播图
2020/02/06 Javascript
Vue左滑组件slider使用详解
2020/08/21 Javascript
[01:54]TI4西雅图DOTA2选手欢迎晚宴 现场报道
2014/07/08 DOTA
详解详解Python中writelines()方法的使用
2015/05/25 Python
Python matplotlib实时画图案例
2020/04/23 Python
OpenCV实现机器人对物体进行移动跟随的方法实例
2020/11/09 Python
python 使用xlsxwriter循环向excel中插入数据和图片的操作
2021/01/01 Python
matplotlib之pyplot模块之标题(title()和suptitle())
2021/02/22 Python
24个canvas基础知识小结
2014/12/17 HTML / CSS
英国顶级水晶珠宝零售商之一:Tresor Paris
2019/04/27 全球购物
美国知名的隐形眼镜电商:Contacts America
2019/11/19 全球购物
招商经理岗位职责
2013/11/16 职场文书
写给老婆的检讨书
2014/02/21 职场文书
超市商业计划书
2014/05/04 职场文书
民事授权委托书范文
2014/08/02 职场文书
查摆问题自查报告范文
2014/10/13 职场文书
资料员岗位职责范本
2015/04/13 职场文书
河童之夏观后感
2015/06/11 职场文书
php远程请求CURL案例(爬虫、保存登录状态)
2021/04/01 PHP
集英社今正式宣布 成立游戏公司“集英社Games”
2022/03/31 其他游戏
【海涛DOTA】D-cup邀请赛NV.cn vs DT.Love
2022/04/01 DOTA