如何实现一个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 相关文章推荐
wxPython框架类和面板类的使用实例
Sep 28 Python
python使用super()出现错误解决办法
Aug 14 Python
Python如何实现MySQL实例初始化详解
Nov 06 Python
EM算法的python实现的方法步骤
Jan 02 Python
对python中raw_input()和input()的用法详解
Apr 22 Python
python执行系统命令后获取返回值的几种方式集合
May 12 Python
python 返回一个列表中第二大的数方法
Jul 09 Python
Python中的单下划线和双下划线使用场景详解
Sep 09 Python
python滑块验证码的破解实现
Nov 10 Python
Python random库使用方法及异常处理方案
Mar 02 Python
Python使用Excel将数据写入多个sheet
May 16 Python
Python 实现简单的客户端认证
Jul 29 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编程中八种常见的文件操作方式
2006/11/19 PHP
Discuz 模板引擎的封装类代码
2008/07/18 PHP
PHP 飞信好友免费短信API接口开源版
2010/07/22 PHP
Laravel框架Eloquent ORM简介、模型建立及查询数据操作详解
2019/12/04 PHP
不错的一个日期输入 动态
2006/11/06 Javascript
javascript encodeURI和encodeURIComponent的比较
2010/04/03 Javascript
单独使用CKFinder选择图片的方法
2010/08/21 Javascript
浅谈javascript面向对象程序设计
2015/01/21 Javascript
JavaScript知识点整理
2015/12/09 Javascript
基于jQuery实现页面搜索功能
2020/03/26 Javascript
从零开始学习Node.js系列教程五:服务器监听方法示例
2017/04/13 Javascript
详解nodejs express下使用redis管理session
2017/04/24 NodeJs
详解AngularJS1.x学习directive 中‘& ’‘=’ ‘@’符号的区别使用
2017/08/23 Javascript
angularjs实现过滤并替换关键字小功能
2017/09/19 Javascript
AngularJS创建一个上传照片的指令实例代码
2018/02/24 Javascript
JavaScript箭头函数中的this详解
2019/06/19 Javascript
Python中使用pprint函数进行格式化输出的教程
2015/04/07 Python
Python获取指定文件夹下的文件名的方法
2018/02/06 Python
TensorFlow实现AutoEncoder自编码器
2018/03/09 Python
python 读取.csv文件数据到数组(矩阵)的实例讲解
2018/06/14 Python
python实现将一个数组逆序输出的方法
2018/06/25 Python
python 实现将字典dict、列表list中的中文正常显示方法
2018/07/06 Python
python pandas cumsum求累计次数的用法
2019/07/29 Python
Missguided美国官网:英国时尚品牌
2018/01/18 全球购物
汇科协同Java笔试题
2012/03/31 面试题
电子信息工程专业推荐信
2014/02/14 职场文书
法人委托书的范本格式
2014/09/11 职场文书
退休党员个人对照检查材料思想汇报
2014/09/29 职场文书
2014年体育部工作总结
2014/11/13 职场文书
挂职个人工作总结
2015/03/05 职场文书
2015年共青团工作总结
2015/05/15 职场文书
2016年10月份红领巾广播稿
2015/12/21 职场文书
python实现简易名片管理系统
2021/04/11 Python
教你使用Python pypinyin库实现汉字转拼音
2021/05/27 Python
javascript的setTimeout()使用方法总结
2021/11/20 Javascript
JS实现九宫格拼图游戏
2022/06/28 Javascript