裝飾器這玩意挺有用,當時感覺各種繞,現在終於繞明白了,俺滴個大爺,還是要慢慢思考才能買明白各種的真諦,沒事就來繞一繞
def outer(func):
def inner():
print("認證成功")
result=func()
print("登入成功")
return result
return inner
@outer
def OA():
print("OA介面")
這裡面需要注意的是:
- @outer和@outer()有區別,沒有括號時,outer函式依然會被執行,這和傳統的用括號才能呼叫函式不同,需要特別注意!
- 是OA這個函式名(而不是OA()這樣被呼叫後)當做引數傳遞給裝飾函式outer,也就是:func = OA,@outer等於outer(OA),實際上傳遞了OA的函式體,而不是執行OA後的返回值。
- outer函式return的是inner這個函式名,而不是inner()這樣被呼叫後的返回值。
1. 程式開始執行outer函式內部的內容,一開始它又碰到了一個函式,inner函式定義塊被程式觀察到後不會立刻執行,而是讀入記憶體中。
2. 再往下,碰到return inner,返回值是個函式名,並且這個函式名會被賦值給OA這個被裝飾的函式,也就是OA = inner,此時OA函式被新的函式inner覆蓋了(實際上是OA這個函式名更改成指向inner這個函式名指向的函式體記憶體地址,OA不再指向它原來的函式體的記憶體地址),再往後呼叫OA的時候將執行inner函式內的程式碼,而不是先前的函式體。那麼先前的函式體去哪了?還記得我們將OA當做引數傳遞給func這個形參麼?func這個變數儲存了老的函式在記憶體中的地址,通過它就可以執行 老的函式體,你能在inner函式裡看到result = func()這句程式碼,它就是這麼做的!
3.接下來,還沒有結束,依然通過OA()的方式呼叫OA 函式時,執行的就不再是老的OA函式的程式碼,而是inner函式的程式碼。在本例中,它首先會列印個“認證成功”的提示,然後,它會執行func函式並將返回值賦值個變數result,這個func函式就是老的OA函式;接著,它又列印了“登陸成功”的提示;最後返回result這個變數。我們可以用 r = OA()的方式接受result的值。
4.僅僅是新增了一個裝飾函式,就實現了我們的需求,在函式呼叫前先認證,呼叫後寫入日誌,這就是裝飾器的最大作用。