自学Python之路-Python基础+模块+面向对象
自学Python之路-Python网络编程
自学Python之路-Python并发编程+数据库+前端
自学Python之路-django
自学Python4.3-装饰器固定格式
1.装饰有返回值的装饰器
import time print(time.time()) def timmer(f): #装饰器函数 def inner(): start = time.time() ret = f() #被装饰的函数 end = time.time() print(end - start) return ret return inner @timmer #语法糖 @装饰器函数名 def func(): #被装饰的函数 time.sleep(0.01) print('我好喜欢大家啊~') return '新年好' # func = timmer(func) ret = func() #inner() print(ret)
以上代码:
执行timmer(func), 返回inner (此时此刻func就是inner) 执行func的时候就是执行inner, 所以在inner里面加个返回值
2. 装饰带参数函数的装饰器
2.1 如果被装饰函数有参数, 有一个参数:
import time print(time.time()) def timmer(f): #装饰器函数 def inner(a): start = time.time() ret = f(a) #被装饰的函数 end = time.time() print(end - start) return ret return inner @timmer #语法糖 @装饰器函数名 def func(a): #被装饰的函数 time.sleep(0.01) print('我好喜欢大家啊',a) return '新年好' # func = timmer(func) ret = func(1) #inner() print(ret)
2.2 如果被装饰函数有参数, 有2个参数:
import time print(time.time()) def timmer(f): #装饰器函数 def inner(a,b): start = time.time() ret = f(a,b) #被装饰的函数 end = time.time() print(end - start) return ret return inner @timmer #语法糖 @装饰器函数名 def func(a,b): #被装饰的函数 time.sleep(0.01) print('我好喜欢大家啊',a,b) return '新年好' # func = timmer(func) ret = func(2598,2417) #inner() print(ret)
2.3 如果被装饰函数有2个,一个函数有1个参数, 另一个函数有2个参数:
import time print(time.time()) def timmer(f): #装饰器函数 def inner(*args): start = time.time() ret = f(*args) #被装饰的函数 end = time.time() print(end - start) return ret return inner @timmer #语法糖 @装饰器函数名 def func1(a): #被装饰的函数func1 time.sleep(0.01) print('我好喜欢大家啊',a) return '新年好' # func = timmer(func) def func2(a,b): #被装饰的函数func2 time.sleep(0.01) print('我爱大家啊',a,b) return '过年好' # func = timmer(func) ret = func1(48785) #inner() ret = func2(2598,2417) #inner() print(ret)
以上只解决了按位置传参数, 但是如果按关键字传参数就会有问题。于是, 可传万能参数
import time print(time.time()) def timmer(f): #装饰器函数 def inner(*args,**kwargs): start = time.time() ret = f(*args,**kwargs) #被装饰的函数 end = time.time() print(end - start) return ret return inner @timmer #语法糖 @装饰器函数名 def func1(a): #被装饰的函数func1 time.sleep(0.01) print('我好喜欢大家啊',a) return '新年好' # func = timmer(func) def func2(a,b): #被装饰的函数func2 time.sleep(0.01) print('我爱大家啊',a,b) return '过年好' # func = timmer(func) ret = func1(48785) #inner() ret = func2(2598,b=2) #inner() print(ret)
3. 引出---装饰器的固定格式
def wrapper(f): #装饰器函数,f是被装饰的函数 def inner(*args,**kwargs): '''在被装饰函数之前要做的事''' ret = f(*args,**kwargs) #被装饰的函数 '''在被装饰函数之后要做的事''' return ret return inner @wrapper #语法糖 @装饰器函数名 def func(a,b): #被装饰的函数 time.sleep(0.01) print('我好喜欢大家',a,b) return '新年好' ret = func()
注意点:
- func 是被装饰的函数
- 调用所有被装饰的函数,其实就是调用的inner
单独打印*args,会将参数打散,输出每一个参数。(接收是聚合,调用是打散)
所以以下的例子,inner(*args) 相当于inner(1,2,3,4)
举例代码:
def wrapper(func): def inner(*args,**kwargs): print('在被装饰的函数执行之前做的事') ret = func(*args,**kwargs) print('在被装饰的函数执行之后做的事') return ret return inner @wrapper #holiday = wrapper(holiday) def holiday(day): print('全体放假%s天'%day) return '好开心' ret = holiday(3) print(ret)
- 1. 执行def wrapper(func) ,放到内存
- 2. 执行holiday=wrapper(holiday)的右部分,传给wrapper下面代码
- 3. 执行def inner(*args,**kwargs)
- 4. return inner 返回地址
- 5. 返回地址给holiday , 赋值
- 6. 执行ret=holiday(3)右部分, 就是相当于inner(3)
- 7. 执行inner函数,print('在被装饰的函数执行之前做的事')
- 8. ret = func(*args,**kwargs) 相当于holiday(*(3),**{})
- 9. 执行函数holiday(3),print('全体放假%s天'%day)
- 10. return “好开心”
- 11. 返回值给ret = func(*args,**kwargs) 的左部分
- 12. print('在被装饰的函数执行之后做的事')
- 13. return ret ,拿到返回值“好开心”
- 14.返回值给holiday=wrapper(holiday)的左部分
- 15.print(ret)
...