如何实现一个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读写Excel文件的实例
Nov 01 Python
Python使用Flask框架同时上传多个文件的方法
Mar 21 Python
深入探究Django中的Session与Cookie
Jul 30 Python
在python3.5中使用OpenCV的实例讲解
Apr 02 Python
基于python requests库中的代理实例讲解
May 07 Python
Python 从一个文件中调用另一个文件的类方法
Jan 10 Python
Python3.5常见内置方法参数用法实例详解
Apr 29 Python
python plotly画柱状图代码实例
Dec 13 Python
django迁移文件migrations的实现
Mar 31 Python
python判断元素是否存在的实例方法
Sep 24 Python
Python数据模型与Python对象模型的相关总结
Jan 26 Python
Python中非常使用的6种基本变量的操作与技巧
Mar 22 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 Errcode: 28 终极解决方法
2009/07/01 PHP
Laravel 5 框架入门(一)
2015/04/09 PHP
详解Grunt插件之LiveReload实现页面自动刷新(两种方案)
2015/07/31 PHP
PHP实现数组向任意位置插入,删除,替换数据操作示例
2019/04/05 PHP
JavaScript基本编码模式小结
2012/05/23 Javascript
javascript去掉前后空格的实例
2013/11/07 Javascript
jquery实现当滑动到一定位置时固定效果
2014/06/17 Javascript
js图片实时加载提供网页打开速度
2014/09/11 Javascript
JavaScript用select实现日期控件
2015/07/17 Javascript
js实现Form栏显示全格式时间时钟效果代码
2015/08/19 Javascript
jQuery实现大转盘抽奖活动仿QQ音乐代码分享
2015/08/21 Javascript
JavaScript对象创建模式实例汇总
2016/10/03 Javascript
jQuery插件HighCharts实现的2D条状图效果示例【附demo源码下载】
2017/03/15 Javascript
jacascript DOM节点——元素节点、属性节点、文本节点
2017/04/18 Javascript
浅谈angular4生命周期钩子
2017/09/05 Javascript
nodejs中密码加密处理操作详解
2018/03/20 NodeJs
详解微信图片防盗链“此图片来自微信公众平台 未经允许不得引用”的解决方案
2019/04/04 Javascript
seajs和requirejs模块化简单案例分析
2019/08/26 Javascript
Vue循环中多个input绑定指定v-model实例
2020/08/31 Javascript
python查找目录下指定扩展名的文件实例
2015/04/01 Python
用Python实现一个简单的能够上传下载的HTTP服务器
2015/05/05 Python
Python的Django框架安装全攻略
2015/07/15 Python
python 与GO中操作slice,list的方式实例代码
2017/03/20 Python
python线程池(threadpool)模块使用笔记详解
2017/11/17 Python
浅谈Python中range和xrange的区别
2017/12/20 Python
Python人工智能之路 之PyAudio 实现录音 自动化交互实现问答
2019/08/13 Python
tensorflow查看ckpt各节点名称实例
2020/01/21 Python
python实现梯度法 python最速下降法
2020/03/24 Python
PyTorch中torch.tensor与torch.Tensor的区别详解
2020/05/18 Python
基于Python的自媒体小助手---登录页面的实现代码
2020/06/29 Python
离婚协议书范本样本
2014/08/19 职场文书
要账委托书范本
2014/09/15 职场文书
语文教师求职信范文
2015/03/20 职场文书
2015年仓库管理工作总结
2015/05/25 职场文书
关于分班的感言
2015/08/04 职场文书
情侣餐厅的创业计划书范本!
2019/07/26 职场文书