如何实现一个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的Flask框架应用调用Redis队列数据的方法
Jun 06 Python
Python3 适合初学者学习的银行账户登录系统实例
Aug 08 Python
微信跳一跳辅助python代码实现
Jan 05 Python
利用python实现微信头像加红色数字功能
Mar 26 Python
windows下python安装pip图文教程
May 25 Python
基于anaconda下强大的conda命令介绍
Jun 11 Python
python 将print输出的内容保存到txt文件中
Jul 17 Python
对Python2与Python3中__bool__方法的差异详解
Nov 01 Python
python实现五子棋游戏
Jun 18 Python
Python操作redis和mongoDB的方法
Dec 19 Python
如何在python中执行另一个py文件
Apr 30 Python
使用Python将语音转换为文本的方法
Aug 10 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 HTML代码串截取代码
2008/12/29 PHP
PHP + plupload.js实现多图上传并显示进度条加删除实例代码
2017/03/06 PHP
javascript学习笔记(一)基础知识
2014/09/30 Javascript
Javascript无参数和有参数类继承问题解决方法
2015/03/02 Javascript
基于jQuery实现瀑布流页面
2017/04/11 jQuery
AngularJS 限定$scope的范围实例详解
2017/06/23 Javascript
switchery按钮的使用方法
2017/12/18 Javascript
Angular实现的内置过滤器orderBy排序与模糊查询功能示例
2017/12/29 Javascript
JavaScript封装的常用工具类库bee.js用法详解【经典类库】
2018/09/03 Javascript
微信小程序中weui用法解析
2019/10/21 Javascript
关于element的表单组件整理笔记
2021/02/05 Javascript
分析Python编程时利用wxPython来支持多线程的方法
2015/04/07 Python
详解使用Python处理文件目录的相关方法
2015/10/16 Python
Python编程中使用Pillow来处理图像的基础教程
2015/11/20 Python
python中requests和https使用简单示例
2018/01/18 Python
Python3实现转换Image图片格式
2018/06/21 Python
python批量赋值操作实例
2018/10/22 Python
对python创建及引用动态变量名的示例讲解
2018/11/10 Python
python接口自动化测试之接口数据依赖的实现方法
2019/04/26 Python
对python3 Serial 串口助手的接收读取数据方法详解
2019/06/12 Python
Pandas删除数据的几种情况(小结)
2019/06/21 Python
Django url,从一个页面调到另个页面的方法
2019/08/21 Python
numpy:np.newaxis 实现将行向量转换成列向量
2019/11/30 Python
Selenium 配置启动项参数的方法
2020/12/04 Python
python 基于PYMYSQL使用MYSQL数据库
2020/12/24 Python
HTML5的hidden属性兼容老浏览器的方法
2014/04/23 HTML / CSS
浅谈html5标签css3的常用样式
2016/10/20 HTML / CSS
次世代生活态度:Hypebeast
2018/07/05 全球购物
Bugatchi官方网站:男士服装在线
2019/04/10 全球购物
用JAVA SOCKET编程,读服务器几个字符,再写入本地显示
2012/11/25 面试题
应届毕业生求职信范文
2014/07/07 职场文书
个人授权委托书格式
2014/08/30 职场文书
环保证明
2015/06/23 职场文书
在人间读书笔记
2015/06/30 职场文书
MySql学习笔记之事务隔离级别详解
2021/05/12 MySQL
vue实现滑动解锁功能
2022/03/03 Vue.js