裝飾器:在本來的程序基礎上新加一些功能(好比判斷餘額、次數登記等)後假裝成原來的程序。閉包
多層裝飾器:
def makeBole(fn): ============>此處是函數作裝飾器,另外還能夠用類作裝飾器
def wrapped():
return "<b>" + fn() + "</b>"
return wrapped
def makeItalic(fn):
def wrapped(*args,**kwargs):
return "<i>" + fn(*args,**kwargs) + "</i>" ========>裝飾器對有參數函數進行裝飾,用*將元組拆開傳遞給真實函數。遇到這種傳遞不定長參數給另一個函數時能夠用這種萬能方法(即:在參數傳遞通道中使用*args,*kwargs)。
return wrappedapp
def canshu(fn,a,b):
print(a,b)
return fn()函數
@canshu(11,22) ========>帶有參數的裝飾器spa
@makeBold =========>等價於test3 = makeBole(test3),注意:makeBole(test3)中的test3爲下面@makeItalic裝飾事後的test3,而非原始test3();
當解釋器執行到這行時會判斷下面是不是一個裝飾器,若是是會先等下面裝飾完再執行。(裝飾器下面只能跟函數和裝飾器,跟變量會出錯)
@makeItalic =========>等價於test3 = makeItalic(test3) =======>裝飾器必須在裝飾時就執行一遍,由於裝飾器裏面包含被裝飾函數內存地址,該地址須要提早加載到內存中,否則裝飾器中被裝飾函數地址會被指
向裝飾後的地址,從而造成死循環(即:裝飾器中調用test3()時調用的若是是被裝飾後的test3則會陷入死循環,因此裝飾器須要在裝飾時就執行一遍以加載至內存中,之後裝飾器中調用test3時就
拿內存中的這一份)。
def test3(a,b,c):
return "hello word"+a+b+c
print(test3(11,22,33)) =========>輸出結果爲:<b><i>hello word112233</i></b>對象
類作裝飾器(沒想明白函數作裝飾器和類作裝飾器各有什麼優劣勢):
class abc(object):
def __init__(self,func):
print('----裝飾的時候這裏會被執行哦------')
self.__func = func
def __call__(self): =========> __call__的做用是當執行「對象()」時會調用該方法(即:經過這個方法能夠把類當作函數去執行)。
print('----裝飾器中的功能-----')
self.__func()
@abc ========>此處至關於 test = abc(test) ,即test指向abc()建立出來的一個對象。
def test():
print('---test---')
test() ========> 此處會調用對象test中的__call__方法,即等價於:test.__call__()。內存
函數作裝飾器的本質是把被裝飾函數重定向到另一個函數上去,而後該函數再重定向到本身的閉包中,在閉包中添加一些「佐料」後再重定向回最原始的被裝飾函數(即:添加「佐料」是在閉包中完成)。
類作裝飾器的本質是把被裝飾函數重定向到一個對象上去,而後利用該對象的__call__()方法對其添加「佐料」後再返回原始的被裝飾函數(即:添加「佐料」是在__call__()方法中完成)it