一:裝飾器緩存
在不改變原函數的基礎上,額外的添加功能。app
裝飾器的返回值是一個函數對象。函數
裝飾器應用:日誌,性能測試,事務處理,緩存等場景。性能
二:裝飾器造成過程測試
一個函數的應用:計算執行時間spa
import time def func1(): print('in func1') def timer(func): def inner(): start_time=time.time() func() end_time=time.time() print(end_time-start_time) return inner func1=timer(func1) func1()
多個函數的應用時候用func1=timer(func1)太麻煩了,因而有了語法糖。.net
不帶參數裝飾器(簡單裝飾器)日誌
import time def timer(func): def inner(): start = time.time() func() print(time.time() - start) return inner @timer #==> func1 = timer(func1) def func1(): print('in func1') func1()
萬能裝飾器(帶參數的函數)對象
def wrapper(func): def inner(*args,**kwargs): ret=func(*args,**kwargs) return ret return inner # @wrapper # def func(): # print() # func()
解讀:省略部分是咱們要調用這個裝飾器執行函數的時候用到的。事務
帶參數裝飾器(查看函數名和聲明信息)
def wrapper(func): def inner(*args,**kwargs): ret=func(*args,**kwargs) return ret return inner @wrapper def func(): print() func()
from functools import wraps def deco(func): @wraps(func) #加在最內層函數正上方 def wrapper(*args,**kwargs): return func(*args,**kwargs) return wrapper @deco def index(): '''哈哈哈哈''' print('from index') print(index.__doc__)
帶flag裝飾器
def outer(flag): print('不用上班') def wrapper(func): print('在挺一週') def inner(*args,**kwargs): if flag: print('裝飾器真頭疼') ret=func(*args,**kwargs) if flag: print('我去,還不完') return ret return inner return wrapper @outer(True) def func(): print('終於放假了') func()
bug:@outer(True)必須放500個
改進
flag = True def wrapper_out(flag): def wrapper(func): def inner(*args,**kwargs): '''執行函數前''' if flag: ret = func(*args,**kwargs) '''執行函數後''' print(222) return ret else: ret = func() return ret return inner return wrapper @wrapper_out(flag) #第一步是調用 wrapper_out(flag),接收到返回值wrapper def func(): #第二步是@wrapper,即func = wrapper(func) print(111) func()
多個裝飾器裝飾一個函數
def wrapper1(func): def inner(): print('wrapper1 ,before func') func() print('wrapper1 ,after func') return inner def wrapper2(func): def inner(): print('wrapper2 ,before func') func() print('wrapper2 ,after func') return inner @wrapper2 @wrapper1 def f(): print('in f') f()