什么是装饰器
#1 开放封闭原则:对扩展是开放的,对修改是封闭的
#2 装饰器本身可以是任意可调用对象,被装饰的对象也可以是任意可调用对象
#3 目的:
'''
在遵循
1. 不修改被装饰对象的源代码
2. 不修改被装饰对象的调用方式
原则下
为被装饰对象加上新功能
'''
1、函数名可以当作函数的参数
1 import time 2 def timmer(func): 3 #函数名可以当做函数的参数 4 def inner(): 5 start = time.time() 6 func() 7 end = time.time() 8 print(end - start) 9 return inner 10 11 def hahaha(): 12 time.sleep(0.1) 13 print('aaaa') 14 15 hahaha() 16 17 输出结果 18 aaaa
2、假如我们不能修改这个函数的调用方式,也不能修改原代码,该怎么做到呢
1 import time 2 def timmer(func): 3 #函数名可以当做函数的参数 4 def inner(): 5 start = time.time() 6 func() 7 end = time.time() 8 print(end - start) 9 return inner 10 11 def hahaha(): 12 time.sleep(0.1) 13 print('aaaa') 14 15 hahaha = timmer(hahaha) #timmer函数的地址给了hahaha 然后在进行调用 16 hahaha() 17 18 aaaa 19 0.10033607482910156
# hahaha = timmer(hahaha) #timmer函数的地址给了hahaha
# hahaha() #实际上执行的是timmer
3、函数传参
1 def timmer(func): #---> hahaha 2 def inner(*args,**kwargs): #动态参数接收从kkk传来的1,2并进行压缩成元组 3 #args == (1,2) kwargs == {} 4 #*args == 1,2 **kwargs == a =1,b = 2 5 func(*args,**kwargs) # ---》kkk #func把值传给kkk并还原,实际上就是解压之前动态参数接收的压缩的值,返回给kkk函数 6 return inner 7 8 9 def kkk(a,b): 10 print(a) 11 12 kkk = timmer(kkk) #timmer函数里的func是kkk函数,然后返回inner函数给kkk 13 kkk(1,2) #kkk函数调用并传参给inner(动态参数*args), 14 15 1
参数
#实参:调用函数的时候传入的参数
#形参
#位置参数:必须传值
1 def aaa(a,b): 2 print(a,b) 3 aaa(1,2)
#默认参数:可以不传
1 def bbb(x=10): #默认参数 没上传参数的话用默认的参数,上传的话会用上传的参数。 2 print(x) 3 bbb() #x = 10 4 bbb(20) #x = 20
#动态参数
1 def ccc(*args):#1,2,3,4,5 #*args 会将ccc上传的参数以元组的方式存放 2 print(args) 3 4 ccc(1,2,3,4,5)#按位置传参数
解压传参
1 def ccc(*args):#1,2,3,4,5 2 print(args) 3 4 #ccc(1,2,3,4,5)#按位置传参数 5 6 t = (1,2,3,4,5) 7 ccc(t) # ((1, 2, 3, 4, 5),) 8 ccc(*t) #(1, 2, 3, 4, 5) #解压
按关键字传参
1 def ddd(**kwargs): #kwargs接收传参然后以字典的方式存放 2 print(kwargs) 3 4 ddd(k = 'a',j = 'b')#按关键字传参数
打散赋值
1 def ccc(*args): 2 print('ccc:',args) #(1,2,3,4,5) 3 def inner(a,b,c,d,e): 4 print('inner',a,b,c,d,e) 5 inner(*args) #*(1,2,3,4,5) 打散 6 7 def inner(a,b,c,d,e): #接收解压的参数然后一一赋值 8 print('inner',a,b,c,d,e) 9 ccc(1,2,3,4,5) 10 inner(1,2,3,4,5)
4、语法糖
1 def timmer(func): #---> jjj 2 def inner(*args,**kwargs): 3 ret = func(*args,**kwargs) # --->ret = jjj() 4 print(ret) 5 return ret 6 return inner 7 8 @timmer #jjj = timmer(jjj) 语法糖 9 def jjj(): 10 return 123 11 12 13 jjj() #ret = jjj() 14 15 16 输出结果 17 123
5、装饰器函数
#装饰器的本质 :闭包函数
#功能:就是在不改变原函数调用方式的情况下,在这个函数前后加上扩展功能
def timmer(func):
def inner(*args,**kwargs):
'''添加函数调用之前的扩展代码'''
ret = func(*args,**kwargs)
'''添加函数调用之后的扩展代码'''
return ret
return inner
#设计模式 原则 开放封闭原则
#对扩展是开放的
#对修改是封闭的
6、装饰器装饰两个函数
1 def wrapper(func):#装饰 2 def inner(*args,**kwargs): 3 4 ret = func(*args,**kwargs) 5 6 return ret 7 return inner 8 9 @wrapper #aaa = wrapper(aaa) 10 def aaa(): 11 print('asghksdlhf') 12 13 @wrapper #bbb = wrapper(bbb) 14 def bbb(): 15 print('asghksdlhf') 16 17 18 aaa() 19 bbb() 20 21 22 #输出结果: 23 #asghksdlhf 24 #asghksdlhf
7、有参装饰器
import time def auth(auth_type): #auth_type='mysql' def auth2(func): def inner(*args,**kwargs): if auth_type == 'file': name=input('name:>> ') pwd=input('password:>> ') if name == 'egon' and pwd == '123': res=func(*args,**kwargs) return res else: print('auth error') elif auth_type == 'mysql': print('mysql auth') else: print('not valid auth source') return inner return auth2 @auth(auth_type='mysql') #@auth2 #index=auth2(最原始的index) #index=inner def index(name): time.sleep(3) print('welcome %s to index' %name) index('egon') #inner('egon')