經典裝飾器程式碼解析
阿新 • • 發佈:2018-11-23
程式碼:
def A(funC):
def B(funE):
def C(*args, **kwargs):
out = funC(funE)(*args,**kwargs)
return out + "...111..."
return C
return B
@A
def C(funE):
def decorated_E_by_C(str):
return funE(str) + "。。。222。。。"
return decorated_E_by_C
@C
def E(str):
return str
print(E("A string is"))
執行結果:
A string is。。。222。。。...111...
程式執行步驟:
- 定義A函式,假設開闢記憶體空間為0x11
- 定義C函式,假設開闢記憶體空間為0x33
- 因為C上有A的裝飾器,所以相當於在定義C後運行了C = A©,所以這個時候要呼叫A函式 ,並把C的函式名,即0x33這個地址傳給了funC
- A函式的呼叫結果是定義了一個B函式,假設開闢記憶體空間為0x22,並把0x22的地址返回給了C這個函式名。此後C相當於指向0x22的函式
- 定義函式E,假設開闢記憶體空間為0x55
- 因為E上有C的裝飾器,所以相當於在定義E後運行了E = C(E),所以這個時候要呼叫C函式 ,並把E的函式名,即0x55這個地址傳給了funE
- 由於C已經指向了0x22,所以呼叫C函式的結果是定義了一個在A函式內部的C函式,這個C和外邊的C不同,可稱之為C2.假設C2的記憶體空間地址為0x44,並把0x44這個地址返回給了E這個函式名。此後E相當於指向0x44的函式
- 最後呼叫E函式,傳入引數為字串‘A string is’。也就是呼叫了0x44的原來的C2的函式,把‘A string is’傳給了(*args, **kwargs)
- 在0x44中,先呼叫了funC函式,其引數是funE。funC指向的是0x33,即最早的C函式。在這個函式中,定義了一個decorated_E_by_C的函式,假設其地址為0x53.建立後,把這個地址返回給了funC(funE)這個整體。所以說funC(funE)就相當於位置在0x53的函式名,後面加括號相當於呼叫這個函式,傳入‘A string is’引數。
- 呼叫0x53處的函式,要返回funE(‘A string is’),加。。。222。。。
- funE直接返回原來的字串‘A string is’,所以0x53最終會返回‘A string is。。。222。。。’ 給了out
- 程式往下執行,返回out+…111…即‘A string is。。。222。。。…111…'給了0x44的函式,也就是E函式。
- 所以最終打印出來‘A string is。。。222。。。…111…'這個字串。