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
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