python编写装饰器_写python中的装饰器
python中的装饰器主要用于在已有函数实现功能前附加需要输出的信息,下面将用实例展示我如何写装饰器。
首先分别尝试写装饰器装饰一个无参函数和一个有参函数(被装饰函数仅输出,无返回值情况下)
1 defmy_log(func):2 defwrapper():3 print('decorator works')4 func()5 return wrapper #返回的只是wrapper函数对象,此时并没有运行
6
7 @my_log8 def run(): #run=my_log(run)=wrapper 返回的是wrapper函数对象,未运行
9 print('run')10
11 run() #run()=wrapper() 此时调用并运行了wrapper()函数
12
13 #运行结果如下
14 #decorator works
15 #run
1 defmy_log(func):2 defwrapper():3 print('decorator works')4 func()5 return wrapper #返回的只是wrapper函数对象,此时并没有运行
6
7 @my_log8 def add(x,y): #add=my_log(add)=wrapper 返回的也是wrapper函数对象,未运行
9 print(x+y)10
11 add(3,6)12 #试图调用并运行wrapper()
13
14 #结果出错
15 #TypeError: wrapper() takes 0 positional arguments but 2 were given
16 #原因是运行add(3,6)时传入了两个参数add(3,6)=wrapper(3,6) 但wrapper()函数中并无参数接收
修改后的正确装饰器函数为(被装饰函数仅输出,无返回值情况下)
1 defmy_log(func):2 defwrapper(x,y):3 print('decorator works')4 func(x,y)5 return wrapper #返回的只是wrapper函数对象,此时并没有运行
6
7 @my_log8 def add(x,y): #add=my_log(add)=wrapper 返回的也是wrapper函数对象,未运行
9 print(x+y)10
11 add(3,6)12
13 #运行结果如下
14 #decorator works
15 #9
但并不是完善的装饰器函数(被装饰函数仅输出,无返回值情况下)
1 defmy_log(func):2 defwrapper(x,y):3 print('decorator works')4 func(x,y)5 return wrapper #返回的只是wrapper函数对象,此时并没有运行
6
7 @my_log8 defadd(x,y):9 print(x+y)10
11 add(3,6)12
13 @my_log14 defrun():15 print('run')16
17 run()18
19 #但添加无参函数run()时又出现了错误
20 #TypeError: wrapper() missing 2 required positional arguments: 'x' and 'y'
21 #因run()=wrapper()未传给wrapper所必需的两个参数
此时需要修改装饰器中wrapper函数为非关键字可变参数和关键字可变参数来保证 无论是否有参数传入都正常运行(被装饰函数仅输出,无返回值情况下)
1 defmy_log(func):2 def wrapper(*args,**kwargs):3 print('decorator works')4 func(*args,**kwargs)5 return wrapper #返回的只是wrapper函数对象,此时并没有运行
6
7 @my_log8 defadd(x,y):9 print(x+y)10
11 add(3,6)12
13 @my_log14 defrun():15 print('run')16
17 run()18
19 #运行结果如下
20 #decorator works
21 #9
22 #decorator works
23 #run
但此时装饰器函数并未完全正确(被装饰函数仅输出,无返回值情况下)
1 defmy_log(func):2 def wrapper(*args,**kwargs):3 print('decorator works')4 func(*args,**kwargs)5 return wrapper #返回的只是wrapper函数对象,此时并没有运行
6
7 @my_log8 defadd(x,y):9 print(x+y)10
11 @my_log12 defrun():13 print('run')14
15 print(run.__name__)16 print(add.__name__)17
18 #运行结果如下
19 #wrapper
20 #wrapper
21 #因run=my_log(run)=wrapper 偷偷修改了run方法和add方法的__name__属性
需要在装饰器函数内部添加@wraps来保证被装饰函数__name__属性不被修改(被装饰函数仅输出,无返回值情况下)
1 from functools importwraps2
3 defmy_log(func):4 @wraps(func)5 def wrapper(*args,**kwargs):6 print('decorator works')7 func(*args,**kwargs)8 return wrapper #返回的只是wrapper函数对象,此时并没有运行
9
10 @my_log11 def run(): #run=my_log(run)=wrapper 返回的是wrapper函数对象,未运行
12 print('running')13
14 run()15 #run()=wrapper()
16
17 print("函数run的__name__是%s"%run.__name__)18 print('-'*30)19
20 @my_log #add=my_log(add)=wrapper 返回的也是wrapper函数对象
21 defadd(a,b):22 print(a+b)23
24 add(3,4)25 #add(3,4)=wrapper(3,4)
26 print("函数add的__name__是%s"%add.__name__)27
28 #运行结果如下
29 #running
30 #函数run的__name__是run
31 #------------------------------
32 #decorator works
33 #7
34 #函数add的__name__是add
被装饰函数有返回值时
1 from functools importwraps2
3
4 #***************错误*************************
5 deflogin_required(func):6 @wraps(func)7 def wrapper(*args,**kwargs):8 print('hello world')9 func(*args,**kwargs)10 returnwrapper11
12 @login_required13 defindex():14 return 'aaaaaaaaaaa'
15
16 a=index()17 print(a)18 #index=login_required()=wrapper
19 #index()=wrapper()
20 #def wrapper(*args,**kwargs):
21 #print('hello world')
22 #index() 此处只是调用index函数得到'aaaaaaaaaaa' 但wrapper函数并未返回该值
23
24 #hello world
25 #None 可见wrapper()调用index()函数并未返回'aaaaaaaaaaa'
26
27 #**************正确********************
28 deflogin_required2(func):29 @wraps(func)30 def wrapper(*args,**kwargs):31 print('hello world')32 return func(*args,**kwargs)33 returnwrapper34
35 @login_required236 defindex():37 return 'aaaaaaaaaaa'
38
39 print('-'*20)40 a=index()41 print(a)42
43
44
45 #输出结果如下
46 #--------------------
47 #hello world
48 #aaaaaaaaaaa
最后总结:
1.装饰器中定义的函数要使用*args 和**kwargs 组合来接收任何可能被装饰函数的参数,在装饰器中的wrapper函数中执行原函数时需传入*args 和**kwargs
2.需使用functools.wraps在装饰器中wrapper函数前将wrapper函数用@wraps包裹,防止被装饰函数__name__属性被修改
以下来自 CS实验室 大佬喵的 https://mp.weixin.qq.com/s?timestamp=1531273713&src=3&ver=1&signature=S-vLsC7yG6GltzbaRovEtemNFSFg3Ps*AQnH1hc3E7-huMUuZbG-i3m0c-8pkEihTO1UIA9wF4Ze8tlMKitOtFb8-eDjsQhYq7KDFDtPZpcotQikbQg8DRhzdgQHArojOFIjBhPb0wAnLzZ2hGn5PXYI4HjRy5CiEpNwr1ii09Y=
1 defred_oil(func):2 print("ready to paint!")3
4 defred_wall_func():5 print("red wall!")6
7 returnred_wall_func8
9
10 @red_oil11 defwall():12 print("wall!")13
14 if __name__=="__main__":15 print("start painting!!!")
执行结果如下:
1 ready to paint!
2 start painting!!!
1 defred_oil(func):2 print("ready to paint!")3
4 defred_wall_func():5 print("red wall!")6
7 returnred_wall_func8
9
10 @red_oil11 defwall():12 print("wall!")13
14 if __name__=="__main__":15 print("start painting!!!")16 wall()
执行结果如下:
1 ready to paint!
2 start painting!!!
3 red wall!
装饰器在被装饰的函数被定义时立即执行,被装饰的函数在运行时才执行。
python编写装饰器_写python中的装饰器相关推荐
- python编写脚本方法_【Python】教你一步步编写banner获取脚本
Hello 各位小伙伴们大家好,周末过的愉快吗? 刚好最近学习了使用python编写banner获取脚本,今天就跟大家一起一步一步再学习一遍吧. Part.1 说明篇 什么是banner? banne ...
- python怎么整体缩进_写python代码时怎么快速的给大量代码加上缩进?
写python代码时怎么快速的给大量代码加上缩进? 已经写了很长的一段代码,突然发现最开始的地方少了个if,之前写的所有代码都要在if之内,原来用c的时候直接加两个花括号就行了,现在用python怎么 ...
- 哪些软件是python编写出来的_用Python编程需要什么软件?
用Python编程需要什么软件?Python编程是一门适合新手入门的编程语言,现在有不少程序员业余时间学习Python编程语言,学习Python找到好工具会大大提高学习的效率.好用的Python编程软 ...
- python编写木马攻击_用Python写一个自动木马程序
电脑作为大家日常办公的工具,最怕的一件事情之一就是被偷,当我们的电脑被盗的时候,不仅仅是电脑本身,更重要的是电脑存储的资料都会丢失.如何尽快的找回电脑需要我们想点办法,今天就教大家一个好的技巧,虽说不 ...
- python编写ftp客户端_用Python写FTP客户端程序
0 前言: ftp客户端相信大家都用过,那么我们为什么还要用Python写ftp客户端呢? 我想有两个原因: 一是写出更好的ftp客户端应用程序,方便大家使用: 二是定制一些特殊服务,例如每天定时下载 ...
- python编写脚本方法_使用Python编写提取日志中的中文的脚本的方法
由于工作需要在一大堆日志里面提取相应的一些固定字符,如果单纯靠手工取提取,数据量大,劳心劳力,于是自然而然想到了用Python做一个对应的提取工具,代替手工提取的繁杂,涉及中文字符,正则表达式不好匹配 ...
- 用python编写学生管理系统_用python写一个简单的学生管理系统
要求如下:1.一个循环2中输入内容的能力.显示函数添加新名片显示所有查询的名片3退出系统.让用户输入所需的操作,如输入1,2,3,04.新列表提示用户输入名称和输入电子邮件提示成功添加新名片.5.显示 ...
- python编写测试系统_纯 python 编写的一套 dubbo 测试平台
因组织要求,需要一个Dubbo接口的测试工具,经多方研究,遂决定要写一个不需要编写任何代码,直接在页面上填写数据就能直接运行Dubbo接口的测试工具,类似于Postman编写http接口一样简单. 整 ...
- 用python编写函数回归分析_用python编写函数的logistic回归系数
下面是逻辑回归的代码.在from sklearn.linear_model import LogisticRegression from sklearn.model_selection import ...
最新文章
- R语言常用包分类总结
- linux设备模型(8)_platform设备,Linux设备模型之platform总线
- python脚本打包rpm_python程序打包rpm包
- calendar操作详解
- Android学习总汇
- 大数据时代的可扩展性数据库集群技术
- 冲击波内幕点滴 (转)
- mysql ubb html_自动闭合HTML/ubb标签函数
- 用网页服务器实现钢琴弹奏(使用Wizwiki-W7500)
- Vue+OpenLayers学习系列(九)Vue+OpenLayers小案例(长度测量、面积测量、坐标定位、坐标获取)
- Kubernetes(k8s)常用资源的使用、Pod的常用操作
- Qt平台添加OpenCV库
- c语言编程560分钟,c语言把560分钟换成小时和分钟表示输出出来
- SVN与GIT两大版本管理工具
- 《操作系统真象还原》第七章
- readv和writev
- 网络安全里的蜜罐、蜜饵、蜜标、蜜网、蜜场……都是啥?
- phpyun6.1人才招聘系统nginx伪静态规则配置
- 自动化脚本编写实例-python
- 【调剂】欢迎调剂模式识别、计算机视觉、虚拟现实方向研究生-上海应用技术大学...
热门文章
- 如何让人工智能拥有情绪?
- 因特尔神经计算棒(NCS)+树莓派+yolo-v3实现object-detection
- TypeError: fit() missing 1 required positional argument: 'y'
- echarts象形柱图的图标怎么更改
- 单片机常用变量定义类型
- 判断两个字符串是否互为回环变位(Circular Rotaion)
- mapreduce实战之空气质量分析(三)
- ArcGIS中的影像解决方案_2019
- 3 - 图片灰度化与转换为八位灰度图片
- Aspose.CAD for Java 20.1版-SEO狼术