Python裝飾器基礎及執行時間
阿新 • • 發佈:2018-12-16
一、裝飾器基礎
裝飾器是可呼叫的物件,其引數是另一個函式(被裝飾的函式)。裝飾器可能會處理被裝飾的函式,然後把他返回,或者將其替換成另一個函式或可呼叫物件。
eg:decorate裝飾器
@decorate
def target():
print("Running target()")
#上面寫法等同於
def target():
print("Running target()")
target = decorate(target)
兩種寫法最終得出來的結果相同,但兩個程式碼執行完畢得到的target不一定是原來那個target函式,而是被decorate(target)返回的函式。
1、裝飾器通常把函式替換成另一個函式
def deco(func): def inner(): print('Running inner()') return inner #deco返回inner函式物件 @deco def target(): #使用deco裝飾target print('Running target()') >>target() #執行target函式,呼叫被裝飾的target其實會執行inner Running inner() >>target #審查物件,發現target現在是inner的引用 <function deco.<locals>.inner at 0x10063b598>
裝飾器只是一種語法糖,裝飾器可以像常規的可呼叫物件一樣呼叫,其引數是另一個函式。裝飾器的一大特性是,能把被裝飾的函式替換為其他函式,裝飾器在載入模組時會立即執行。
二、何時執行裝飾器
裝飾器在被裝飾的函式定義後會立即執行。
eg:registration.py模組
registry = [] #registry儲存被@registry裝飾的函式引用 def register(func): #register的引數是一個函式 print("Running register(%s)" % func) #顯示被裝飾的函式 registry.append(func) #把func存入registry return func #返回func:必須返回函式;這裡返回的函式與通過引數傳入的一樣 @register #f1,f2被@register裝飾 def f1(): print("Running f1()") @register def f2(): print("Running f2()") def f3(): #f3沒用被裝飾 print("Running f3()") def main(): #main顯示registry,然後呼叫f1()、f2()、f3() print("Running main()") print("Registry ->",registry) f1() f2() f3() if __name__ == "__main__": main() #只有把registration.py當作指令碼執行時才呼叫main()
上述程式碼輸出如下:
$python3 registration.py
Running register(<function f1 at 0x1000631bf8>)
Running register(<function f1 at 0x1000631c80>)
Running main()
registry -> [<function f1 at 0x1000631bf8> ,<function f1 at 0x1000631c80>]
Running f1()
Running f2()
Running f3()
載入模組後,register中有兩個被裝飾函式的引用:f1、f2。這兩個函式,以f3,只有在main明確呼叫它們才執行。
如果匯入registration.py模組(不作為指令碼執行),輸出如下:
import registration
Running register(<function f1 at 0x10063b1e0>)
Running register(<function f2 at 0x10063b237>)
函式裝飾器在匯入模組時立即執行,而被裝飾函式只在明確呼叫時執行