python —— 装饰器函数
装饰器
装饰器原则:遵循开放封闭原则。对外扩展开放;对修改是封闭。
装饰器的作用:在不改变原函数的情况下,在函数前后添加新的功能
装饰器的本质:闭包函数
先看思维导图能更好的学习装饰器函数

1、基础版本的装饰器模板:
1 def wrapper(func): 2 def inner(*args,**kwargs): 3 print('被装饰函数前添加内容') 4 ret = func(*args,**kwargs) #被装饰函数,在这里指 my_func 函数 5 print('被装饰函数后添加内容') 6 return ret 7 return inner 8 9 @wrapper # 等价于 my_func = wrapper(my_func)相当于:my_func = inner 10 def my_func(): #正常定义的函数,也就是要被装饰的函数 11 c = 1+3 12 return c 13 14 #函数调用 15 g = my_func() # my_func ==inner 16 print(g) # 4
直接过程如图所示:

2、练习:在不改变定义的my_func程序中,测试代码执行的时间?
1 import time 2 def wrapper(func): 3 def inner(*args,**kwargs): 4 start_time = time.time() 5 ret = func(*args,**kwargs) #被装饰函数,在这里指 my_func 函数 6 time.sleep(0.01) 7 end_time = time.time() 8 print('程序执行时间为:',(end_time - start_time)) 9 return ret 10 return inner 11 12 @wrapper # 等价于 my_func = wrapper(my_func)相当于:my_func = inner 13 def my_func(): #正常定义的函数,也就是要被装饰的函数 14 c = 1+3 15 return c 16 17 #函数调用 18 g = my_func() # my_func ==inner 19 print(g) # 4
如果有一天同事想取到您这个函数明德时候,上述装饰器就不能正确的给出,存在缺陷,如图:

解决办法:
1 import time 2 from functools import wraps 3 def wrapper(func): 4 @wraps(func) 5 def inner(*args,**kwargs): 6 start_time = time.time() 7 ret = func(*args,**kwargs) #被装饰函数,在这里指 my_func 函数 8 time.sleep(0.01) 9 end_time = time.time() 10 print('程序执行时间为:',(end_time - start_time)) 11 return ret 12 return inner 13 14 @wrapper # 等价于 my_func = wrapper(my_func)相当于:my_func = inner 15 def my_func(): #正常定义的函数,也就是要被装饰的函数 16 c = 1+3 17 return c 18 19 #函数调用 20 g = my_func() # my_func ==inner 21 print(g) # 4 22 print(my_func.__name__) # my_func 获取函数名
3、函数是可以传参的,那么装饰器能否传参呢?
假如:领导要检测您程序运行时间,我们定义装饰器函数,检测过后,要如何删除装饰或者关闭装饰器呢?
1 import time 2 inp = input('是否开启装饰器(y/n):') 3 flag = True if inp == 'y' else False #装饰器开关标志位 4 def outer(flag): 5 def wrapper(func): 6 def inner(*args,**kwargs): 7 if flag: 8 start_time = time.time() 9 ret = func(*args,**kwargs) #被装饰函数,在这里指 my_func 函数 10 time.sleep(0.01) 11 end_time = time.time() 12 print('程序执行时间为:',(end_time - start_time)) 13 else: 14 ret = func(*args,**kwargs) 15 return ret 16 return inner 17 return wrapper 18 19 @outer(flag) #先执行outer(flag),返回wrapper函数:--》 @wrapper 20 def my_func(): #正常定义的函数,也就是要被装饰的函数 21 c = 1+3 22 return c 23 24 #函数调用 25 g = my_func() # my_func ==inner 26 print(g) #4
4、 有些时候,我们也会用到多个装饰器装饰同一个函数的情况。
wrapper1(func): def inner1(*args,**kwargs): ret = func(*args,**kwargs) #被装饰的函数 return ret return inner1 def wrapper2(func): def inner2(*args,**kwargs): ret = func(*args,**kwargs) #被装饰的函数 return ret return inner2 @wrapper1 @wrapper2 def my_func(): print('*********') return('11111')

浙公网安备 33010602011771号