day3-python之装饰器(四)

1、简单的装饰器python

装饰器本质上就是一个python函数,可让其余函数在不须要任何代码变更的前提下,增长额外的功能,装饰器的返回值也是一个函数对象。缓存

简单来说,在原有的函数先后增长功能,且不改变原函数的调用方式。闭包

装饰器的本质:就是一个闭包函数app

装饰器的应用场景:插入日志、性能测试、事务处理、缓存等等场景。ide

实现计算每一个函数的执行时间的功能:函数

 1 import time
 2 def timmer(f):
 3     def inner():
 4         start_time = time.time()
 5         f()
 6         end_time = time.time()
 7         print(end_time - start_time)
 8     return inner
 9 
10 def func():
11     print('begin func')
12     time.sleep(0.1)
13     print('end func')
14 
15 func = timmer(func)
16 func()   # ==> inner()
简单的装饰器

以上功能不简洁,不完美。引出语法糖。性能

 1 import time
 2 def timmer(f):
 3     def inner():
 4         start_time = time.time()
 5         f()
 6         end_time = time.time()
 7         print(end_time - start_time)
 8     return inner
 9 
10 @timmer   # ==>  func = timmer(func)
11 def func():
12     print('begin func')
13     time.sleep(0.1)
14     print('end func')
15 
16 func()   # ==> inner()
装饰器-------语法糖

以上装饰器都是不带参数函数,如今装饰一个带参数的该怎么办?测试

 1 import time
 2 def timmer(f):
 3     def inner(*args,**kwargs):
 4         start_time = time.time()
 5         ret = f(*args,**kwargs)
 6         end_time = time.time()
 7         print(end_time - start_time)
 8         return ret
 9     return inner
10 
11 @timmer   # ==>  func = timmer(func)
12 def func(a,b):
13     print('begin func',a)
14     time.sleep(0.1)
15     print('end func',b)
16     return True
17 
18 func(1,2)   # ==> inner()
原函数带多个参数的装饰器
 1 import time  2 
 3 def timer(func):  4     def inner(a):  5         start = time.time()  6  func(a)  7         print(time.time() - start)  8     return inner  9 
10 @timer 11 def func1(a): 12     print(a) 13 
14 func1(1)
原函数带一个参数的装饰器
 1 import time  2 def timer(func):  3     def inner(*args,**kwargs):  4         start = time.time()  5         re = func(*args,**kwargs)  6         end=time.time()  7         print(end- start)  8         return re  9     return inner 10 
11 @timer   #==> func1 = timer(func1)
12 def func1(a,b): 13     print('in func1') 14     print(a,b) 15 
16 @timer   #==> func1 = timer(func1)
17 def func2(a): 18     print('in func2 and get a:%s'%(a)) 19     return 'fun2 over'
20 
21 func1(1,2) 22 print(func2('aaaaaa'))
原函数带多个参数的装饰器
 1 import time  2 def timer(func):  3     def inner(*args,**kwargs):  4         start = time.time()  5         re = func(*args,**kwargs)  6         end=time.time()  7         print(end - start)  8         return re  9     return inner 10 
11 @timer   #==> func1 = timer(func1)
12 def jjj(a): 13     print('in jjj and get a:%s'%(a)) 14     return 'fun2 over'
15 
16 jjj('aaaaaa') 17 print(jjj('aaaaaa'))
带返回值的装饰器

2、开放封闭原则spa

1.对扩展是开放的
任何一个程序,不可能在设计之初就已经想好了全部的功能而且将来不作任何更新和修改。因此咱们必须容许代码扩展、添加新功能。
2.对修改是封闭的
由于咱们写的一个函数,颇有可能已经交付给其余人使用了,若是这个时候咱们对其进行了修改,颇有可能影响其余已经在使用该函数的用户。
装饰器完美的遵循了这个开放封闭原则。设计

3、装饰器的固定结构

1 def timmer(f):
2     def inner(*args,**kwargs):
3         '''执行函数以前要作的'''
4         ret = f(*args,**kwargs)
5         '''执行函数以后要作的'''
6         return ret
7     return inner
装饰器的固定格式
装饰器的固定格式--wraps版

4、带参数的装饰器

带参数的装饰器:就是给装饰器传参

用处:就是当加了不少装饰器的时候,如今突然又不想加装饰器了,想把装饰器给去掉,可是那么多代码,一个一个去显得麻烦,因此,能够利用带参数的装饰器去装饰它,就像一个开关,须要的时候就打开调用,不须要的时候就关闭去掉。给装饰器里面传个参数,那么这个语法糖也要带个括号。在语法糖括号内传参。能够用三层嵌套,弄一个标识

 1 # 带参数的装饰器:(至关于开关)为了给装饰器传参
 2 F=True#为True时就把装饰器给加上了
 3 # F=False#为False时就把装饰器给去掉了
 4 def outer(flag):  5     def wrapper(func):  6         def inner(*args,**kwargs):  7             if flag:  8                 print('before')  9                 ret=func(*args,**kwargs) 10                 print('after') 11             else: 12                 ret = func(*args, **kwargs) 13             return ret 14         return inner 15     return wrapper 16 
17 @outer(F)#@wrapper
18 def hahaha(): 19     print('hahaha') 20 
21 @outer(F) 22 def shuangwaiwai(): 23     print('shuangwaiwai') 24 
25 hahaha() 26 shuangwaiwai()
给装饰器加参数

5、多个装饰器装饰一个函数

 1 def qqqxing(fun):  2     def inner(*args,**kwargs):  3         print('in qqxing: before')  4         ret = fun(*args,**kwargs)  5         print('in qqxing: after')  6         return ret  7     return inner  8 
 9 def pipixia(fun): 10     def inner(*args,**kwargs): 11         print('in qqxing: before') 12         ret = fun(*args,**kwargs) 13         print('in qqxing: after') 14         return ret 15     return inner 16 @qqqxing 17 @pipixia 18 def dapangxie(): 19     print('饿了吗') 20 dapangxie() 21 
22 '''
23 @qqqxing和@pipixia的执行顺序:先执行qqqxing里面的 print('in qqxing: before'),而后跳到了pipixia里面的 24  print('in qqxing: before') 25  ret = fun(*args,**kwargs) 26  print('in qqxing: after'),完了又回到了qqqxing里面的 print('in qqxing: after')。因此就以下面的运行结果截图同样 27 '''
多个装饰器装饰一个函数

 6、进阶需求

第一种状况:

# 500个函数

# 设计你的装饰器 从而确认是够生效

 1 import time
 2 def outer(flag):
 3     def timmer(f):
 4         def inner(*args,**kwargs):
 5             if flag == True:
 6                 start_time = time.time()
 7                 ret = f(*args,**kwargs)
 8                 end_time = time.time()
 9                 print(end_time - start_time)
10             else:
11                 ret = f(*args,**kwargs)
12             return ret
13         return inner
14     return timmer
15 
16 @outer(False)
17 def func(a,b):
18     print('begin func',a)
19     time.sleep(0.1)
20     print('end func',b)
21     return True
22 
23 func(1,2)
带参数的装饰器

 第二种状况:

# 装饰器:登陆、记录日志

 1 login_info = {'alex':False}
 2 def login(func):
 3     def inner(name):
 4         if login_info[name] != True:
 5             user = input('user:')
 6             pwd = input('pwd:')
 7             if user == 'alex' and pwd == 'alex3714':
 8                 login_info[name] = True
 9         if login_info[name] == True:
10             ret = func(name)
11             return ret
12     return inner
13 
14 @login
15 def index(name):
16     print('欢迎%s来到博客园首页~' %name)
17 
18 @login
19 def manager(name):
20     print('欢迎%s来到博客园管理页~' %name)
21 
22 index('alex')
23 index('alex')
24 manager('alex')
25 manager('alex')
登陆装饰器
 1 import time
 2 login_info = {'alex':False}
 3 def login(func):   # manager
 4     def inner(name):
 5         if login_info[name] != True:
 6             user = input('user :')
 7             pwd = input('pwd :')
 8             if user == 'alex' and pwd == 'alex3714':
 9                 login_info[name] = True
10         if login_info[name] == True:
11             ret = func(name)     # timmer中的inner
12             return ret
13     return inner
14 
15 def timmer(f):
16     def inner(*args,**kwargs):
17         start_time = time.time()
18         ret = f(*args,**kwargs)     # 调用被装饰的方法
19         end_time = time.time()      #
20         print(end_time - start_time)
21         return ret
22     return inner
23 
24 @login
25 @timmer
26 def index(name):
27     print('欢迎%s来到博客园首页~'%name)
28 
29 @login
30 @timmer    # manager = login(manager)
31 def manager(name):
32     print('欢迎%s来到博客园管理页~'%name)
33 
34 index('alex')
35 index('alex')
36 manager('alex')
37 manager('alex')
登陆、记录日志装饰器
 1 l=[]  2 def wrapper(fun):  3     l.append(fun)#统计当前程序中有多少个函数被装饰了
 4     def inner(*args,**kwargs):  5         # l.append(fun)#统计本次程序执行有多少个带装饰器的函数被调用了
 6         ret = fun(*args,**kwargs)  7         return ret  8     return inner  9 
10 @wrapper 11 def f1(): 12     print('in f1') 13 
14 @wrapper 15 def f2(): 16     print('in f2') 17 
18 @wrapper 19 def f3(): 20     print('in f3') 21 print(l)
统计多少个函数被装饰了

 

7、总结

# 装饰器的进阶
# 给装饰器加上一个开关 - 从外部传了一个参数到装饰器内
# 多个装饰器装饰同一个函数 - 套娃
# 每一个装饰器都完成一个独立的功能
# 功能与功能之间互相分离
# 同一个函数须要两个或以上额外的功能
 1 def wrapper1(func):
 2     def inner(*args,**kwargs):
 3         '''执行a代码'''
 4         ret = func(*args,**kwargs)
 5         '''执行b代码'''
 6         return ret
 7     return inner
 8 
 9 def wrapper2(func):
10     def inner(*args,**kwargs):
11         '''执行c代码'''
12         ret = func(*args,**kwargs)
13         '''执行d代码'''
14         return ret
15     return inner
16 
17 @wrapper1
18 @wrapper2
19 def func():pass
相关文章
相关标签/搜索