Python进阶-IV-Wrapper高阶
一、装饰器回顾:
1、标准的装饰器示例
1 def trapper(func): 2 def inner(*args, **kwargs): 3 print('插入到被装饰函数前的功能!') 4 res = func(*args, **kwargs) 5 print('插入到被装饰函数后的功能!') 6 return res 7 8 return inner 9 10 11 @trapper 12 def func(): 13 print('this is func!') 14 15 16 func()
2、代码运行时间装饰器的优化
考虑如果同时有500个函数要解除检查代码运行时间,会不会费太多时间取注释掉语法糖?
是不是可以用标志控制,只改它就可以关闭或者打开装饰器
1 import time 2 ON_OFF = True # 装饰器控制开关,默认是关的 3 4 5 def count_time(func): 6 def inner(*args, **kwargs): 7 global ON_OFF # 如果不能使用该关键字,毕竟不安全 8 if ON_OFF: 9 start = time.time() 10 res = func(*args, **kwargs) 11 end = time.time() 12 print('the function run use: %s'%(end - start)) 13 return res 14 re = func(*args, **kwargs) 15 return re 16 17 return inner 18 19 20 @count_time 21 def func_wrapped(): 22 time.sleep(0.233) 23 print('wrapping me!') 24 25 26 @count_time 27 def woqu(): 28 time.sleep(0.31415926) 29 print('wo ququququuuuuuuuu') 30 31 func_wrapped() 32 woqu()
3、高阶优化代码运行时间装饰器
如果不使用global关键字,在局部域中使用全局变量,毕竟不安全,如何改造?
1 ef timmer_out(flag): # 在装饰器外再加一层函数,传入标志位,函数的最多嵌套三层! 2 def timmer(func): 3 def inner(*args, **kwargs): 4 if ON_OFF: 5 start = time.time() 6 res = func(*args, **kwargs) 7 end = time.time() 8 print('the function run use: %s' % (end - start)) 9 return res 10 re = func(*args, **kwargs) 11 return re 12 13 return inner 14 return timmer 15 16 @timmer_out(ON_OFF) # --> 等同于先执行timmer_out(ON_OFF)函数,返回:timmer;接着执行@timmer语法糖 17 def func_use_time(): 18 time.sleep(0.233) 19 print('use ti me!') 20 21 22 @timmer_out(ON_OFF) 23 def func_waste_time(): 24 time.sleep(0.31415926) 25 print('wo waste') 26 27 func_use_time() 28 func_waste_time()
二、@wraps的使用
解决在被装饰函数得不到原本函数名的问题
1 print(func.__name__) # 打印的结果时:inner ,因为被装饰后,func = trapper(func) 即 func = inner 2 # 如何得到它原本的名字了? 3 # 引入库 4 from functools import wraps 5 6 7 def a_new_trapper(a_func): 8 @wraps(a_func) 9 def wrap_the_function(): 10 print("I am doing some boring work before executing a_func()") 11 a_func() 12 print("I am doing some boring work after executing a_func()") 13 14 return wrap_the_function 15 16 17 @a_new_trapper 18 def a_function_requiring_trapper(): 19 """Hey yo! Decorate me!""" 20 print("I am the function which needs some trap to " 21 "remove my foul smell") 22 23 24 print('a_function_requiring_trapper.__name__') 25 print(a_function_requiring_trapper.__name__)
三、多层装饰器
即多个装饰器同时装饰一个函数;
引入场景:网上购物时登录后,其他操作如:添加商品到购物车,删除购物车中的商品就不用再登录了!
同时登录用户的每个动作都要记录到日志中。
1 FLAG = False 2 3 4 def login(func): 5 @wraps(func) # 此处也要加,否者写入日志的还是inner 6 def inner(*args, **kwargs): 7 global FLAG 8 while 1: 9 if FLAG is False: 10 name = input('请输入您的登录名:') 11 passwd = input('请输入您的登录密码:') 12 if name == 'lisi' and passwd == '1234': 13 FLAG = True 14 break 15 print('您输入的密码或者登录名不正确!请重新输入!') 16 continue 17 break 18 res = func(*args, **kwargs) 19 return res 20 21 return inner 22 23 24 def log(func): 25 @wraps(func) 26 def inner(*args, **kwargs): 27 res = func(*args, **kwargs) 28 with open('log', mode='a', encoding='utf-8') as f: 29 f.write(func.__name__ + '\n') 30 return res 31 32 return inner 33 34 35 @log 36 @login 37 def add_merc_to_cart(): 38 print('I just add some merchandise to the cart!') 39 40 41 @log 42 @login 43 def del_merc_in_cart(): 44 print('I just del some merchandise in the cart!') 45 46 47 add_merc_to_cart() 48 del_merc_in_cart()
多层装饰器的标准演示流程
1 ef wrapper1(func): 2 def inner(*args, **kwargs): 3 print('第一个装饰器wrapper1,在函数前的添加!') 4 res = func(*args, **kwargs) 5 print('第一个装饰器wrapper1,在函数后的添加!') 6 return res 7 8 return inner 9 10 11 def wrapper2(func): 12 def inner2(*args, **kwargs): 13 print('第二个装饰器wrapper2,在函数前的添加!') 14 res = func(*args, **kwargs) 15 print('第二个装饰器wrapper3,在函数后的添加!') 16 return res 17 18 return inner2 19 20 21 def wrapper3(func): 22 def inner3(*args, **kwargs): 23 print('第三个装饰器wrapper3,在函数前的添加!') 24 res = func(*args, **kwargs) 25 print('第三个装饰器wrapper3,在函数后的添加!') 26 return res 27 28 return inner3 29 30 31 @wrapper3 32 @wrapper2 33 @wrapper1 34 def wuha(): 35 print('wu haaaaaaaaaaaaaaaaa!') 36 37 38 wuha()

浙公网安备 33010602011771号