python中装饰器的作用_Python中装饰器的用法
装饰器的作用
当我们需要为函数拓展新的功能,但是又不能修改函数的内部结构时,就可以通过装饰器来完成。通过装饰器为函数拓展功能符合“对于扩展是开放的,对于修改是封闭的”这一开闭原则。下面我们将通过六个步骤了解如何使用装饰器。
步骤一
我们先定义一个函数f,现在我们需要为其添加运行时打印出当前时间的功能,我们可以通过改变内部代码来完成:
deff():print('this is f')--------------------------------
importtimedeff():print(time.time())print('this is f')
f()
步骤二
步骤一在函数内部添加打印时间代码显然不符合开闭原则。换种思路,我们可以定义一个新函数getTime,将f作为参数传入,执行getTime来实现拓展功能:
importtimedeff():print('this is f')defgetTime(func):print(time.time())
func()
getTime(f)
步骤三
步骤二中使用getTime确实实现了功能拓展,但是我们的本意是为f函数拓展功能,由调用getTime函数来实现显然不够友好。让我们换一种getTime的实现形式:
importtimedefdecorator(func):defwrapper():print(time.time())
func()returnwrapperdeff():print('this is f')
d=decorator(f)
d()
我们使用了闭包的结构来实现getTime,内部的wrapper函数和原来的getTime函数完全相同。我们先调用decorator将wrapper返回给变量d,然后通过d来调用wrapper实现原来getTime的功能。具体细节可以看Python中的作用域及闭包一文中关于闭包的实现。
步骤四
在步骤三中我们不但需要调用新的变量d来实现功能,并且还增加了代码的复杂度,可以说甚至不如步骤二中的实现。但是当我们使用了@这个语法糖后情况就将会改变:
importtimedefdecorator(func):defwrapper():print(time.time())
func()returnwrapper
@ decoratordeff():print('this is f')
f()
当我们为f函数打上@decorator装饰器后,我们就可以直接调用f来实现功能,真正实现了对f函数的功能拓展。(@只是一种语法糖,这种方式看似只调用了f函数,实际调用过程与步骤三中相同,最后都是调用了内部的wrapper来实现)
步骤五
在步骤四中我们已经初步实现了装饰器,但如果f函数是一个需要传入参数的函数我们该如何修改:
使用@前:
importtimedefdecorator(func):defwrapper(n):print(time.time())
func(n)returnwrapperdeff(n):print('this is f' +n)
d=decorator(f)
d('.')
我们在wrapper函数的定义时加上参数n,在其内部调用f函数时传入参数n,并在外部用d来调用wrapper时传入参数。
使用@后:
importtimedefdecorator(func):defwrapper(n):print(time.time())
func(n)returnwrapper
@ decoratordeff(n):print('this is f' +n)
f('.')
加上装饰器后我们直接在调用f函数时传入参数,对于wrapper中的修改与上面相同。
步骤六
步骤五中我们实现了只传入一个参数的函数装饰器,那么如果我们事先不知道被装饰的函数会有几个参数我们该怎样定义装饰器?这就需要使用如下两个变长参数:
*args:变长参数元组
**kwargs:变长关键字参数字典
在wrapper中使用这两个变长参数后我们就得到了完整的装饰器,可以用来装饰含有任意参数个数和类型的函数:
importtimedefdecorator(func):def wrapper(*args, **kwargs):print(time.time())
func(*args, **kwargs)returnwrapper
@ decoratordeff(n):print('this is f' +n)
@ decoratordeff2(n,m):print('this is f2' + n +m)
f('.')
f2('.','。')
python中装饰器的作用_Python中装饰器的用法相关推荐
- python中格式化字符串的作用_python中字符串格式化的意义(化妆)
格式 描述 %%百分号标记 #就是输出一个% %c字符及其ASCII码 %s字符串 %d有符号整数(十进制) %u无符号整数(十进制) %o无符号整数(八进制) %x无符号整数(十六进制) %X无符号 ...
- python中yield语句的作用_Python中关键字yield有什么作用
python中,yield关键字的作用:1.将一个函数修改为生成器,利用生成器可以有效地节约系统资源,避免不必要的内存占用:2.用于定义上下文管理器:3.协程:4.配合from形成yield from ...
- python中匿名函数的作用_Python 中的匿名函数,你会用吗
原标题:Python 中的匿名函数,你会用吗 概念 我们从一个例子引入. 这里有一个元素为非空字符串的列表,按字符串最后一个字母将列表进行排序.如果原列表是 ['abc', 'g', 'def'],则 ...
- python if name main 的作用_Python中if __name__ == '__main__':的作用和原理
if __name__ == '__main__':的作用 一个python文件通常有两种使用方法,第一是作为脚本直接执行,第二是 import 到其他的 python 脚本中被调用(模块重用)执行. ...
- python中的变量的作用_Python中的变量作用域
python中变量作用域包括: L (Local) 局部作用域,函数内部声明但没有使用global的变量 E (Enclosing) 闭包函数外的函数中,def或者lambda的本地作用域 G (Gl ...
- python if name main 的作用_Python中if __name__ == __main__: 的作用
在很多python脚本中在最后的部分会执行一个判断语句if __name__ == "__main__:",之后还可能会有一些执行语句.那添加这个判断的目的何在? 在python编 ...
- python中的array函数作用_Python中的Array | 数组2(简介和功能)
相关文章:Python中的数组Array | 1(简介和功能) 以下是更多函数. 1. typecode:此函数返回初始化数组所用的数据类型. 2. itemsize:此函数返回单个数组元素的大小(以 ...
- python中sorted函数的作用_Python中排序方法sort、函数sorted的key参数的作用分析
从Python2.4开始,list.sort方法 和 sorted方法 都增加了一个 'key' 参数用来在进行比较之前指定每个列表元素上要调用的函数,将函数的返回值作为比较的依据. 那么怎么使用这个 ...
- python中continue语句的作用_Python中Continue语句的用法的举例详解
Python continue语句返回while循环的开始.Continue语句拒绝在该循环的当前迭代中的其余语句执行并移动控制返回到循环的顶部(开始位置). continue语句可以在while和f ...
最新文章
- 于明:必应发力海外业务 中国搜索营销市场暗流涌动
- 某熊周刊:一周推荐外文技术资料(12.2)
- linux播放视频的最简单方法
- C语言增量内存申请 realloc
- Intellij IDEA 默认打开上次项目设置与取消设置
- strtus2改成springboot_jdk1.6环境下struts2改spring boot方案
- 判断JavaScript对象为null或者属性为空
- uva 10396——Vampire Numbers
- Windows下pip 离线包安装
- 记一次es和mq的netty冲突
- 20190822:(leetcode习题)字符串转换整数 (atoi)
- 扩充你的工具箱 - 大行文件的处理
- Oracle EBS-SQL (OM-2):检查OM常用表
- Vue电商网站项目开发总结
- MATLAB非线性可视化之线性系统相图
- java 从服务器下载文件并保存到本地
- css背景随机,CSS如何随机定义网页中的背景颜色
- 基于线程池实现多线程任务
- 16个千兆光口8个千兆Combo光电复用口管理型工业以太网交换机环网+WEB管理+SNMP+VLAN
- OCJP 1Z0-808考题解析 题31--60