如何实现一个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去掉字符串中空格的方法
Mar 11 Python
python基础教程之序列详解
Aug 29 Python
python生成ppt的方法
Jun 07 Python
Python Django切换MySQL数据库实例详解
Jul 16 Python
Django框架模型简单介绍与使用分析
Jul 18 Python
python base64库给用户名或密码加密的流程
Jan 02 Python
python读取图片的几种方式及图像宽和高的存储顺序
Feb 11 Python
Python基于stuck实现scoket文件传输
Apr 02 Python
python利用xpath爬取网上数据并存储到django模型中
Feb 26 Python
pytorch--之halfTensor的使用详解
May 24 Python
Python多线程 Queue 模块常见用法
Jul 04 Python
代码复现python目标检测yolo3详解预测
May 06 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面向对象分析设计的经验原则
2008/09/20 PHP
php 表单提交大量数据发生丢失的解决方法
2014/03/03 PHP
PHP使用适合阅读的格式显示文件大小的方法
2015/03/05 PHP
Ubuntu中启用php的mail()函数并解决发送邮件速度慢问题
2015/03/27 PHP
php微信公众平台交互与接口详解
2016/11/28 PHP
JavaScript中统计Textarea字数并提示还能输入的字符
2014/06/10 Javascript
javascript实现分栏显示小技巧附图
2014/10/13 Javascript
jQuery中事件与动画的总结分享
2016/05/24 Javascript
js接收并转化Java中的数组对象的方法
2016/08/11 Javascript
使用vue如何构建一个自动建站项目
2018/02/05 Javascript
详解VUE-地区选择器(V-Distpicker)组件使用心得
2018/05/07 Javascript
js canvas实现画图、滤镜效果
2018/11/27 Javascript
vue-for循环嵌套操作示例
2019/01/28 Javascript
如何为你的JavaScript代码日志着色详解
2019/04/08 Javascript
详解微信小程序开发聊天室—实时聊天,支持图片预览
2019/05/20 Javascript
详解vue组件之间的通信
2020/08/30 Javascript
[19:14]DOTA2 HEROS教学视频教你分分钟做大人-维萨吉
2014/06/24 DOTA
对于Python编程中一些重用与缩减的建议
2015/04/14 Python
使用Pyinstaller的最新踩坑实战记录
2017/11/08 Python
Python提取频域特征知识点浅析
2019/03/04 Python
浅谈Django中view对数据库的调用方法
2019/07/18 Python
Python使用configparser读取ini配置文件
2020/05/25 Python
Spy++的使用方法及下载教程
2021/01/29 Python
图库照片、免版税图片、矢量艺术、视频片段:Depositphotos
2019/08/02 全球购物
进修护士自我鉴定
2013/10/14 职场文书
医学生自我鉴定范文
2013/11/08 职场文书
财务会计自荐信范文
2014/02/21 职场文书
论文诚信承诺书
2014/05/23 职场文书
施工安全协议书范本
2014/09/26 职场文书
单位婚育证明范本
2014/11/21 职场文书
2015年度企业工作总结
2015/05/21 职场文书
实习单位意见
2015/06/04 职场文书
邹越演讲观后感
2015/06/15 职场文书
dubbo集成zipkin获取Traceid的实现
2021/07/26 Java/Android
微信小程序结合ThinkPHP5授权登陆后获取手机号
2021/11/23 PHP
gojs实现蚂蚁线动画效果
2022/02/18 Javascript