1、装饰器介绍:
装饰器本质上就是一个python函数,他可以让其他函数在不需要做任何改变的前提下,增加一些额外的功能,而装饰器的返回值也是一个函数对象。
2、装饰器遵循的原则:
(1) 不修改被装饰函数的原代码。
(2) 不修改被装饰函数的调用方式。
写代码要遵循开发封闭原则,虽然在这个原则是用面向对象开发的,但是也适用于函数式编程,简单来说,它规定已经实现功能的代码不允许被修改,但是可以被扩展,即:
封闭:已经实现功能的代码块
开放:对扩展功能的开发
3、装饰器的实现方法:
(1)装饰器固定格式:
def wrappers(fun):
def inner(*args,**kwargs):
"""被装饰函数执行前的操作"""
ret = fun(*args,**kwargs)
"""被装饰函数执行后的操作"""
return ret
return inner
(2)无参装饰器:
示例:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import time
def wrappers(fun):
def inner(*args,**kwargs):
start_time = time.time()
ret = fun(*args,**kwargs)
end_time = time.time()
print('此函数执行时间为%s'%(end_time - start_time))
return ret
return inner
@wrappers #这样的写法被称为语法糖
def func1(): #这个函数为打印99乘法表
for i in range(1,10):
for n in range(1,10):
print(i,'x',n,"=",n*i,'\t',end='')
if i == n:
print('')
break
func1() #执行函数
结果:
(3) 有参装饰器:
示例:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import time
2 def timmer(a): #在原来的基础上的外面再套一层函数
3 def wrappers(f):
4 def inner(*args,**kwargs):
5 if a:
6 start = time.time()
7 ret = f(*args,**kwargs)
8 stop = time.time()
9 print(stop - start)
10 else:
11 ret = f(*args, **kwargs)
12 return ret
13 return inner
14 return wrappers
15
16 flag = True #定义一个标志位,如果是True的话,则被装饰的函数全部执行,如果是False的话,则所以被装饰的函数都不
17
18 @timmer(flag) #执行时:
19 1、@和timmer(flag)会分开执行,先执行timmer(flag),然后返回一个wrappers.
20 2、接下来在结合@和wrappers执行,执行的就是一个原本的装饰器了
21 def reg1():
22 time.sleep(0.245)
23 print('很复杂。。。')
24
25 @timmer(flag)
26 def reg2():
27 time.sleep(0.245)
28 print('特别复杂。。。')
29
30 @timmer(flag)
31 def reg3():
32 time.sleep(0.245)
33 print('非常复杂。。。')
34 reg1()
35 reg2()
36 reg3()
(4) 多个装饰器装饰一个函数:
示例:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
4、函数信息__doc__和__name__使用:
(1) __doc__的使用:
a、不加载wraps模块的结果:(显示出来的是装饰器的解释信息)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 def wrappers(f):
2 def inner1(*args,**kwargs):
3 """装饰器解释信息"""
4 print('函数运行前func1')
5 ret = f(*args,**kwargs)
6 print('函数运行后func1')
7 return ret
8 return inner1
9
10 @wrappers
11 def func1():
12 """被装饰函数的解释信息"""
13 print('正在运行此函数')
14
15 print(func1.__doc__)
结果:
b、加载wraps模块的结果:(结果读取的是被装饰的函数的解释信息)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 from functools import wraps 2 def wrappers(f): 3 @wraps(f) 4 def inner1(*args,**kwargs): 5 '''装饰器解释信息''' 6 print('函数运行前func1') 7 ret = f(*args,**kwargs) 8 print('函数运行后func1') 9 return ret 10 return inner1 11 12 @wrappers 13 def func1(): 14 """被装饰函数的解释信息""" 15 print('正在运行此函数') 16 17 print(func1.__doc__)
结果:
(2) __name__的使用:(显示真正执行的函数的名字)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 def wrappers(f): #f = func1 2 def inner1(*args,**kwargs): 3 '''装饰器解释信息''' 4 print('函数运行前func1') 5 ret = f(*args,**kwargs) #f() = func1() 6 print('函数运行后func1') 7 return ret 8 return inner1 9 10 @wrappers #func1 = wrappers(func1),外部的func1等于inner1 11 def func1(): 12 """被装饰函数的解释信息""" 13 print('正在运行此函数') 14 15 func1() #func1() = inner1() 16 17 print(func1.__name__) ##值为inner1
结果: