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中的装饰器相关推荐

  1. python编写脚本方法_【Python】教你一步步编写banner获取脚本

    Hello 各位小伙伴们大家好,周末过的愉快吗? 刚好最近学习了使用python编写banner获取脚本,今天就跟大家一起一步一步再学习一遍吧. Part.1 说明篇 什么是banner? banne ...

  2. python怎么整体缩进_写python代码时怎么快速的给大量代码加上缩进?

    写python代码时怎么快速的给大量代码加上缩进? 已经写了很长的一段代码,突然发现最开始的地方少了个if,之前写的所有代码都要在if之内,原来用c的时候直接加两个花括号就行了,现在用python怎么 ...

  3. 哪些软件是python编写出来的_用Python编程需要什么软件?

    用Python编程需要什么软件?Python编程是一门适合新手入门的编程语言,现在有不少程序员业余时间学习Python编程语言,学习Python找到好工具会大大提高学习的效率.好用的Python编程软 ...

  4. python编写木马攻击_用Python写一个自动木马程序

    电脑作为大家日常办公的工具,最怕的一件事情之一就是被偷,当我们的电脑被盗的时候,不仅仅是电脑本身,更重要的是电脑存储的资料都会丢失.如何尽快的找回电脑需要我们想点办法,今天就教大家一个好的技巧,虽说不 ...

  5. python编写ftp客户端_用Python写FTP客户端程序

    0 前言: ftp客户端相信大家都用过,那么我们为什么还要用Python写ftp客户端呢? 我想有两个原因: 一是写出更好的ftp客户端应用程序,方便大家使用: 二是定制一些特殊服务,例如每天定时下载 ...

  6. python编写脚本方法_使用Python编写提取日志中的中文的脚本的方法

    由于工作需要在一大堆日志里面提取相应的一些固定字符,如果单纯靠手工取提取,数据量大,劳心劳力,于是自然而然想到了用Python做一个对应的提取工具,代替手工提取的繁杂,涉及中文字符,正则表达式不好匹配 ...

  7. 用python编写学生管理系统_用python写一个简单的学生管理系统

    要求如下:1.一个循环2中输入内容的能力.显示函数添加新名片显示所有查询的名片3退出系统.让用户输入所需的操作,如输入1,2,3,04.新列表提示用户输入名称和输入电子邮件提示成功添加新名片.5.显示 ...

  8. python编写测试系统_纯 python 编写的一套 dubbo 测试平台

    因组织要求,需要一个Dubbo接口的测试工具,经多方研究,遂决定要写一个不需要编写任何代码,直接在页面上填写数据就能直接运行Dubbo接口的测试工具,类似于Postman编写http接口一样简单. 整 ...

  9. 用python编写函数回归分析_用python编写函数的logistic回归系数

    下面是逻辑回归的代码.在from sklearn.linear_model import LogisticRegression from sklearn.model_selection import ...

最新文章

  1. R语言常用包分类总结
  2. linux设备模型(8)_platform设备,Linux设备模型之platform总线
  3. python脚本打包rpm_python程序打包rpm包
  4. calendar操作详解
  5. Android学习总汇
  6. 大数据时代的可扩展性数据库集群技术
  7. 冲击波内幕点滴 (转)
  8. mysql ubb html_自动闭合HTML/ubb标签函数
  9. 用网页服务器实现钢琴弹奏(使用Wizwiki-W7500)
  10. Vue+OpenLayers学习系列(九)Vue+OpenLayers小案例(长度测量、面积测量、坐标定位、坐标获取)
  11. Kubernetes(k8s)常用资源的使用、Pod的常用操作
  12. Qt平台添加OpenCV库
  13. c语言编程560分钟,c语言把560分钟换成小时和分钟表示输出出来
  14. SVN与GIT两大版本管理工具
  15. 《操作系统真象还原》第七章
  16. readv和writev
  17. 网络安全里的蜜罐、蜜饵、蜜标、蜜网、蜜场……都是啥?
  18. phpyun6.1人才招聘系统nginx伪静态规则配置
  19. 自动化脚本编写实例-python
  20. 【调剂】欢迎调剂模式识别、计算机视觉、虚拟现实方向研究生-上海应用技术大学...

热门文章

  1. 如何让人工智能拥有情绪?
  2. 因特尔神经计算棒(NCS)+树莓派+yolo-v3实现object-detection
  3. TypeError: fit() missing 1 required positional argument: 'y'
  4. echarts象形柱图的图标怎么更改
  5. 单片机常用变量定义类型
  6. 判断两个字符串是否互为回环变位(Circular Rotaion)
  7. mapreduce实战之空气质量分析(三)
  8. ArcGIS中的影像解决方案_2019
  9. 3 - 图片灰度化与转换为八位灰度图片
  10. Aspose.CAD for Java 20.1版-SEO狼术