如何实现一个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写的贪吃蛇游戏例子
Jun 16 Python
Python中的__slots__示例详解
Jul 06 Python
python如何爬取个性签名
Jun 19 Python
对Pytorch神经网络初始化kaiming分布详解
Aug 18 Python
python标准库os库的函数介绍
Feb 12 Python
Python networkx包的实现
Feb 14 Python
Django微信小程序后台开发教程的实现
Jun 03 Python
Python调用百度OCR实现图片文字识别的示例代码
Jul 17 Python
Python 在局部变量域中执行代码
Aug 07 Python
plt.figure()参数使用详解及运行演示
Jan 08 Python
Python 将代码转换为可执行文件脱离python环境运行(步骤详解)
Jan 25 Python
python数字图像处理之图像的批量处理
Jun 28 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学习笔记之 函数声明(二)
2011/06/09 PHP
php实现的SESSION类
2014/12/02 PHP
PHP简单实现HTTP和HTTPS跨域共享session解决办法
2015/05/27 PHP
JavaScript的类型简单说明
2010/09/03 Javascript
js DOM 元素ID就是全局变量
2012/09/20 Javascript
通过jQuery源码学习javascript(三)
2012/12/27 Javascript
javascript 获取模态窗口的滚动位置代码
2013/08/06 Javascript
如何动态的导入js文件具体该怎么实现
2014/01/14 Javascript
JavaScript字符串对象fromCharCode方法入门实例(用于把Unicode值转换为字符串)
2014/10/17 Javascript
详解Node.js如何开发命令行工具
2016/08/14 Javascript
jquery编写日期选择器
2017/03/16 Javascript
在一个页面实现两个zTree联动的方法
2017/12/20 Javascript
vue.js实现带日期星期的数字时钟功能示例
2018/08/28 Javascript
详解vue-router导航守卫
2019/01/19 Javascript
详解JavaScript实现动态的轮播图效果
2019/04/29 Javascript
axios实现简单文件上传功能
2019/09/25 Javascript
javascript实现贪吃蛇游戏(娱乐版)
2020/08/17 Javascript
[03:22]DSPL第一期精彩集锦:酷炫到底!
2014/11/07 DOTA
Python 解析XML文件
2009/04/15 Python
2款Python内存检测工具介绍和使用方法
2014/06/01 Python
python使用fileinput模块实现逐行读取文件的方法
2015/04/29 Python
python2.7到3.x迁移指南
2018/02/01 Python
Python爬虫:url中带字典列表参数的编码转换方法
2019/08/21 Python
python实现移动木板小游戏
2020/10/09 Python
基于Python实现全自动下载抖音视频
2020/11/06 Python
介绍一下EJB的体系结构
2012/08/01 面试题
师范学院教师自荐书
2014/01/31 职场文书
班级活动策划书
2014/02/06 职场文书
创建文明城市标语
2014/06/16 职场文书
中层干部培训方案
2014/06/16 职场文书
党员对照检查材料
2014/09/22 职场文书
2016学校元旦晚会经典开场白台词
2015/12/03 职场文书
团队合作精神学习心得体会
2016/01/19 职场文书
《刷子李》教学反思
2016/02/20 职场文书
详解overflow:hidden的作用(溢出隐藏、清除浮动、解决外边距塌陷)
2021/07/01 HTML / CSS
python神经网络Xception模型
2022/05/06 Python