python3 装饰器全解
2018-08-21 05:42:59来源:博客园 阅读 ()
本章结构:
1.理解装饰器的前提准备
2.装饰器:无参/带参的被装饰函数,无参/带参的装饰函数
3.装饰器的缺点
4.python3的内置装饰器
5.本文参考
理解装饰器的前提:1.所有东西都是对象(函数可以当做对象传递) 2.闭包
闭包的概念:
1)函数嵌套
2)内部函数使用外部函数的变量
3)外部函数的返回值为内部函数
下面写一个最为简单的闭包的例子:
1 def test(name): 2 def test_in(): 3 print(name) 4 return test_in 5 6 func = test('whyz') 7 func()
装饰器的原型:
1 import time 2 def showtime(func): 3 def wrapper(): 4 start_time = time.time() 5 func() 6 end_time = time.time() 7 print('spend is {}'.format(end_time - start_time)) 8 9 return wrapper 10 11 def foo(): 12 print('foo..') 13 time.sleep(3) 14 15 foo = showtime(foo) 16 foo()
不带参数的装饰器:(装饰器,被装饰函数都不带参数)
1 import time 2 def showtime(func): 3 def wrapper(): 4 start_time = time.time() 5 func() 6 end_time = time.time() 7 print('spend is {}'.format(end_time - start_time)) 8 9 return wrapper 10 11 @showtime #foo = showtime(foo) 12 def foo(): 13 print('foo..') 14 time.sleep(3) 15 16 @showtime #doo = showtime(doo) 17 def doo(): 18 print('doo..') 19 time.sleep(2) 20 21 foo() 22 doo()
带参数的被装饰的函数
1 import time 2 def showtime(func): 3 def wrapper(a, b): 4 start_time = time.time() 5 func(a,b) 6 end_time = time.time() 7 print('spend is {}'.format(end_time - start_time)) 8 9 return wrapper 10 11 @showtime #add = showtime(add) 12 def add(a, b): 13 print(a+b) 14 time.sleep(1) 15 16 @showtime #sub = showtime(sub) 17 def sub(a,b): 18 print(a-b) 19 time.sleep(1) 20 21 add(5,4) 22 sub(3,2)
带参数的装饰器(装饰函数),
实际是对原有装饰器的一个函数的封装,并返回一个装饰器(一个含有参数的闭包函数),
当使用@time_logger(3)调用的时候,Python能发现这一层封装,并将参数传递到装饰器的环境去
1 import time 2 def time_logger(flag = 0): 3 def showtime(func): 4 def wrapper(a, b): 5 start_time = time.time() 6 func(a,b) 7 end_time = time.time() 8 print('spend is {}'.format(end_time - start_time)) 9 10 if flag: 11 print('将此操作保留至日志') 12 13 return wrapper 14 15 return showtime 16 17 @time_logger(2) #得到闭包函数showtime,add = showtime(add) 18 def add(a, b): 19 print(a+b) 20 time.sleep(1) 21 22 add(3,4)
类装饰器:一般依靠类内部的__call__方法
1 import time 2 class Foo(object): 3 def __init__(self, func): 4 self._func = func 5 6 def __call__(self): 7 start_time = time.time() 8 self._func() 9 end_time = time.time() 10 print('spend is {}'.format(end_time - start_time)) 11 12 @Foo #bar = Foo(bar) 13 def bar(): 14 print('bar..') 15 time.sleep(2) 16 17 bar()
使用装饰器的缺点:
1.位置错误的代码->不要在装饰器之外添加逻辑功能
2.不能装饰@staticmethod 或者 @classmethod已经装饰过的方法
3.装饰器会对原函数的元信息进行更改,比如函数的docstring,__name__,参数列表:
下面对装饰器第第三个缺点进行剖析,
1 import time 2 def showtime(func): 3 def wrapper(): 4 start_time = time.time() 5 func() 6 end_time = time.time() 7 print('spend is {}'.format(end_time - start_time)) 8 9 return wrapper 10 11 @showtime #foo = showtime(foo) 12 def foo(): 13 print('foo..') 14 time.sleep(3) 15 16 def doo(): 17 print('doo..') 18 time.sleep(2) 19 20 print(foo.__name__) 21 print(doo.__name__)
结果为:
wrapper
doo
由此可以看出,装饰器会对原函数的元信息进行更改,可以使用wraps,进行原函数信息的添加
注解:wraps本身也是一个装饰器,他能把函数的元信息拷贝到装饰器函数中使得装饰器函数与原函数有一样的元信息
以下是一个wraps的例子:
1 import time 2 from functools import wraps 3 def showtime(func): 4 5 @wraps(func) 6 def wrapper(): 7 start_time = time.time() 8 func() 9 end_time = time.time() 10 print('spend is {}'.format(end_time - start_time)) 11 12 return wrapper 13 14 @showtime #foo = showtime(foo) 15 def foo(): 16 print('foo..') 17 time.sleep(3) 18 19 def doo(): 20 print('doo..') 21 time.sleep(2) 22 23 print(foo.__name__) 24 print(doo.__name__)
结果为:
foo
doo
常用的内置装饰器:1.staticmethod: 类似实现了静态方法 注入以后,可以直接 : 类名.方法
2.property:经过property装饰过的函数 不再是一个函数,而是一个property,类似实现get,set方法
1 @property 2 def width(self): 3 return self.__width 4 5 @width.setter 6 def width(self, newWidth): 7 self.__width = newWidth
3.classmethod: 与staticmethod很相似,貌似就只有这一点区别:
第一个参数需要是表示自身类的 cls 参数,
可以来调用类的属性,类的方法,实例化对象等。
本文参考:
1.https://www.cnblogs.com/vamei/archive/2013/02/16/2820212.html
2.https://www.cnblogs.com/wupeiqi/articles/4980620.html
3.https://www.cnblogs.com/yuanchenqi/articles/5830025.html
4.https://blog.csdn.net/mdzzname/article/details/78702440
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
- python3基础之“术语表(2)” 2019-08-13
- python3 之 字符串编码小结(Unicode、utf-8、gbk、gb2312等 2019-08-13
- Python3安装impala 2019-08-13
- Python之装饰器笔记 2019-08-13
- python3 enum模块的应用 2019-08-13
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash