1 面试的时候,经常被问过装饰器,所以掌握好装饰器非常重要。 2 一.装饰器形成的过程:1.最简单的装饰器。2.被装饰的函数有返回值。3.被装饰的函数有一个参数。4.被装饰的函数有多个位置参数。5.被装饰的函数有多个位置参数和关键字参数。 3 二.装饰器的作用:不修改被装饰的函数的代码和调用方式,增加新的功能。 4 三.原则:开放封闭原则。 5 四.语法糖:@wrapper 6 五.装饰器的固定模式。 7 8 9 一.装饰器形成的过程:1.最简单的装饰器。注意:下面代码没修改被装饰的函数的代码,但是调用使用了timmer(test)而不是test(),改变了调用方式,会导致 10 以前调用该函数的程序发生错误(如果以前有人使用过你写的函数)。 11 使用 时间函数 计算 代码 运行的时间 12 import time 13 def timmer(t): #timmer(t)是时间装饰器 14 start = time.time() #开始:函数开始运行的时间 15 time.sleep(0.01) #让函数睡眠0.01秒,否则打印的结果是0.0。 16 t() #过程:函数运算的过程。t()表示调用被装饰的函数。 17 end = time.time() #结束:函数结束运行的时间 18 print(end-start) #打印出运算的过程需要多少时间 19 def test(): 20 print('今天必须非常努力,我要寻找热爱学习热爱工作的自己,我会为自己的努力而感到快乐幸福和满足') 21 timmer(test) #把需要计算运行时间的函数对象(或者说是地址)传给时间函数timmer 22 23 24 1.在不准修改test函数的情况下,装饰器发挥非常重要的作用:不修改test函数的代码,那么调用test函数的方式也不能修改,但是想在函数前后增加功能。 25 2.下面例子,test()这种调用函数的方式没有改变,但是给test函数增加了计算运行时间的功能。 26 3.开放封闭原则:对拓展(增加功能)是开放的,但是对修改被装饰的函数是封闭的。 27 28 一.装饰器形成的过程:1.最简单的装饰器:不修改被装饰的函数的代码和调用方式,使用了内部函数和闭包。 29 import time 30 def timmer(f): #装饰器函数 31 def inner(): 32 start = time.time() 33 time.sleep(0.01) 34 f() #被装饰的函数 35 end = time.time() 36 print(end-start) 37 return inner #test=timmer(test)=inner,返回inner的id给timmer(test) 38 test = timmer(test) 39 def test(): 40 print('今天必须非常努力,我要寻找热爱学习热爱工作的自己,我会为自己的努力而感到快乐和幸福和满足') 41 test() #test()=inner() 42 43 44 45 #一.装饰器形成的过程:2.被装饰的函数有返回值。 46 import time 47 def timmer(f): #装饰器函数 48 def inner(): 49 start = time.time() 50 time.sleep(0.01) 51 n = f() #被装饰的函数 52 end = time.time() 53 print(end-start) 54 return n 55 return inner #test=timmer(test)=inner,返回inner的id给timmer(test) 56 test = timmer(test) 57 def test(): #被装饰的函数 58 print('今天必须非常努力,我要寻找热爱学习热爱工作的自己,我会为自己的努力而感到快乐和幸福和满足') 59 return 10000000 60 print(test()) #test()=inner() 61 62 63 #一.装饰器形成的过程:3.被装饰的函数有一个参数。 64 import time 65 def timmer(f): #装饰器函数 66 def inner(a): 67 start = time.time() 68 time.sleep(0.01) 69 n = f(a) #被装饰的函数 70 end = time.time() 71 print(end-start) 72 return n 73 return inner #test=timmer(test)=inner,返回inner的id给timmer(test) 74 test = timmer(test) 75 def test(a): #被装饰的函数 76 print('加油',a) 77 return 10000000 78 print(test(10000000)) #test(a)=inner(a) 79 80 81 一.装饰器形成的过程:4.被装饰的函数有多个位置参数。 82 import time 83 def timmer(f): #装饰器函数 84 def inner(*args): 85 start = time.time() 86 time.sleep(0.01) 87 n = f(*args) #被装饰的函数 88 end = time.time() 89 print(end-start) 90 return n 91 return inner #test=timmer(test)=inner,返回inner的id给timmer(test) 92 test = timmer(test) 93 def test(*args): #被装饰的函数 94 print('加油',args) 95 return 10000000 96 print(test(1,2,3)) #test(*args)=inner(*args) 97 98 99 #一.装饰器形成的过程:5.被装饰的函数有多个位置参数和关键字参数。 100 import time 101 def timmer(f): #装饰器函数 102 def inner(*args,**kwargs): 103 start = time.time() 104 time.sleep(0.01) 105 n = f(*args,**kwargs) #被装饰的函数 106 end = time.time() 107 print(end-start) 108 return n 109 return inner #test=timmer(test)=inner,返回inner的id给timmer(test) 110 test = timmer(test) 111 def test(*args,**kwargs): #被装饰的函数 112 print('加油',args,kwargs) 113 return 10000000 114 print(test(1,2,3,t=8000000,m=10000000)) #test(*args,**kwargs)=inner(*args,**kwargs) 115 116 117 四.语法糖:@wrapper 118 import time 119 def timmer(f): 120 def inner(): 121 start = time.time() 122 time.sleep(0.01) 123 n = f() 124 end = time.time() 125 print(end - start)
return n 126 return inner 127 @timmer #语法糖@timmer相当于 func=timmer(func) 没有语法糖或func=timmer(func),装饰器就无法起作用。 128 def func(): 129 print('今天继续加油') 130 func() 131 132 133 134 五.装饰器的固定模式。wrapper是装饰的意思。 135 def wrapper(f): 136 def inner(*args,**kwargs): 137 '''在被装饰的函数前面增加功能''' 138 ret = f(*args,**kwargs) 139 '''在被装饰的函数后面增加功能''' 140 return ret 141 return inner #上面五句话是装饰器的固定模式。 142 @wrapper 143 def func(*args,**kwargs): 144 return args,kwargs 145 print(func(1,2,3,m=10000000)) 146 147 六.装饰器的执行过程: 148 1. def wrapper(f): 149 4. def inner(*args,**kwargs): 150 7. '''在被装饰的函数前面增加功能''' 151 8. ret = f(*args,**kwargs) 152 9. '''在被装饰的函数后面增加功能''' 153 10. return ret #返回func(1,2,3,m=10000000)的返回值,因为第6步使用了print,所以被装饰的函数的返回值就被打印出来。 154 5. return inner #返回inner给wrapper(func),那么inner=wrapper(func)=func 155 3. @wrapper #func=wrapper(func)传参 156 2. def func(*args,**kwargs): 157 return args,kwargs 158 6. print(func(1,2,3,m=10000000)) #func=inner,相当于print(inner(1,2,3,m=10000000)),接着内部函数inner执行。 159 调用func函数实际上是调用了装饰器的内部函数:inner函数。