Python何時執行裝飾器


裝飾器的一個關鍵特性是,它們在被裝飾的函數定義之后立即運行。這 通常是在導入時(即 Python 加載模塊時),如示例 7-2 中的 registration.py 模塊所示。
  示例 7-2 registration.py 模塊
registry = []

def register(func):
    print('running register(%s)' % func)
    registry.append(func)
    return func

@register
def f1():
    print('running f1()')

@register
def f2():
    print('running f2()')

def f3():
    print('running f3()')

def main():
    print('running main()')
    print('registry ->', registry)
    f1()
    f2()
    f3()

if __name__ == '__main__':
    main()

運行結果

running register(<function f1 at 0x0000027913AA8708>)
running register(<function f2 at 0x0000027913AA8E58>)
running main()
registry -> [<function f1 at 0x0000027913AA8708>, <function f2 at 0x0000027913AA8E58>]
running f1()
running f2()
running f3()
注意,register 在模塊中其他函數之前運行(兩次)。調用 register 時,傳給它的參數是被裝飾的函數,例如 0x100631bf8>。
加載模塊后,registry 中有兩個被裝飾函數的引用:f1 和 f2。這兩 個函數,以及 f3,只在 main 明確調用它們時才執行。
如果導入 registration.py 模塊(不作為腳本運行),輸出如下:
>>> import registration
running register(<function f1 at 0x10063b1e0>)
running register(<function f2 at 0x10063b268>)
此時查看 registry 的值,得到的輸出如下:
>>> registration.registry
[<function f1 at 0x10063b1e0>, <function f2 at 0x10063b268>]
示例 7-2 主要想強調,函數裝飾器在導入模塊時立即執行,而被裝飾的 函數只在明確調用時運行。這突出了 Python 程序員所說的導入時和運 行時之間的區別。
考慮到裝飾器在真實代碼中的常用方式,示例 7-2 有兩個不尋常的地 方。
  裝飾器函數與被裝飾的函數在同一個模塊中定義。實際情況是,裝 飾器通常在一個模塊中定義,然后應用到其他模塊中的函數上。
  register 裝飾器返回的函數與通過參數傳入的相同。實際上,大 多數裝飾器會在內部定義一個函數,然后將其返回。
雖然示例 7-2 中的 register 裝飾器原封不動地返回被裝飾的函數,但 是這種技術並非沒有用處。很多 Python Web 框架使用這樣的裝飾器把函 數添加到某種中央注冊處,例如把 URL模式映射到生成 HTTP 響應的函 數上的注冊處。這種注冊裝飾器可能會也可能不會修改被裝飾的函數。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM