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()
View Code

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()
View Code

 

二、@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__)
View Code

 

三、多层装饰器

即多个装饰器同时装饰一个函数;
引入场景:网上购物时登录后,其他操作如:添加商品到购物车,删除购物车中的商品就不用再登录了!
同时登录用户的每个动作都要记录到日志中。
 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()
View Code
多层装饰器的标准演示流程
 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()
View Code
posted @ 2019-11-27 10:33  四方游览  阅读(311)  评论(0)    收藏  举报