如何实现一个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判断、获取一张图片主色调的2个实例
Apr 10 Python
Python性能优化的20条建议
Oct 25 Python
使用Python程序抓取新浪在国内的所有IP的教程
May 04 Python
简单的python后台管理程序
Apr 13 Python
Python正则表达式经典入门教程
May 22 Python
Python 实现淘宝秒杀的示例代码
Jan 02 Python
Python实现的爬虫刷回复功能示例
Jun 07 Python
python3 mmh3安装及使用方法
Oct 09 Python
python 使用shutil复制图片的例子
Dec 13 Python
Python 操作 MySQL数据库
Sep 18 Python
python 如何把docker-compose.yaml导入到数据库相关条目里
Jan 15 Python
Python解析m3u8拼接下载mp4视频文件的示例代码
Mar 03 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和MySQL保存和输出图片
2006/10/09 PHP
PHP将整个网站生成HTML纯静态网页的方法总结
2012/02/05 PHP
PHP按行读取、处理较大CSV文件的代码实例
2014/04/09 PHP
yii2中添加验证码的实现方法
2016/01/09 PHP
PHP实现基于mysqli的Model基类完整实例
2016/04/08 PHP
解决Laravel 不能创建 migration 的问题
2019/10/09 PHP
『jQuery』.html(),.text()和.val()的概述及使用
2013/04/22 Javascript
jquery实现的Banner广告收缩效果代码
2015/09/02 Javascript
jQuery遍历DOM的父级元素、子级元素和同级元素的方法总结
2016/07/07 Javascript
jQuery简单实现title提示效果示例
2016/08/01 Javascript
JQuery遍历元素的后代和同胞实现方法
2016/09/18 Javascript
JavaScript实现前端分页控件
2017/04/19 Javascript
jQuery输入框密码的显示隐藏【代码分享】
2017/04/29 jQuery
xmlplus组件设计系列之图标(ICON)(1)
2017/05/05 Javascript
layui实现多图片上传并限制上传的图片数量
2019/09/26 Javascript
使用p5.js实现动态GIF图片临摹重现
2019/10/23 Javascript
[02:56]DOTA2矮人直升机 英雄基础教程
2013/11/26 DOTA
Python的多态性实例分析
2015/07/07 Python
详解Python3中的Sequence type的使用
2015/08/01 Python
python用10行代码实现对黄色图片的检测功能
2015/08/10 Python
Python3使用requests发闪存的方法
2016/05/11 Python
python中正则表达式与模式匹配
2019/05/07 Python
python动态进度条的实现代码
2019/07/03 Python
对Python获取屏幕截图的4种方法详解
2019/08/27 Python
Keras 利用sklearn的ROC-AUC建立评价函数详解
2020/06/15 Python
13个Pandas实用技巧,助你提高开发效率
2020/08/19 Python
如何解决python多种版本冲突问题
2020/10/13 Python
STUBHUB日本:购买和出售全球活动门票
2018/07/01 全球购物
英国最大最好的无人机商店:Drones Direct
2019/07/12 全球购物
办公室文员工作自我评价
2013/12/01 职场文书
医药专业应届毕业生求职信范文
2014/01/01 职场文书
商场促销活动方案
2014/02/08 职场文书
2014公安机关纪律作风整顿思想汇报
2014/09/13 职场文书
党员评议个人总结
2014/10/20 职场文书
MYSQL 表的全面总结
2021/11/11 MySQL
Hive导入csv文件示例
2022/06/25 数据库