Python 裝飾器爲什麼要雙層嵌套

參考鏈接:
  1. python裝飾器爲什麼要雙層嵌套函數
  2. python裝飾器爲什麼要雙層嵌套

從上述回答中的幾個有助於裝飾器理解的 關鍵點:

  • 裝飾器發生在 定義 階段而不是 執行 階段。
  • 裝飾器返回的是一個被裝飾過的 函數定義
  • 結合第二點理解now = foo(now)

原因:

如果沒有嵌套,實際上裝飾器返回的要麼是原函數的定義,要麼根本不是函數,也就是說函數根本沒有被裝飾。

即使碰巧得到了想要的結果也是裝飾器在定義的階段便運行的,這其實是不應該發生的,因爲這意味着不調用函數,照樣會有輸出,而且效果不能在函數被調用時復現。

代碼說明如下

無嵌套示例:
def foo(func):      # 裝飾器內部無嵌套
    print ("[INFO]: now exe {}()".format(func.__name__))
    return func
    
@foo
def hello(x):
    print ("hello {}!".format(x))

此時直接運行上述代碼是會打印出[INFO]: now exe hello()的,然而此處並沒有調用hello

如果碰巧在上述代碼末尾加上了hello(x="world"),那麼將會輸出:

[INFO]: now exe hello()
hello world!

這完全足以以假亂真了,實際情況是定義階段產生了第一條輸出,真正調用時只產生了第二條。

嵌套寫法:
def foo(func):      # 裝飾器內部有嵌套
    def wrapper(*args, **kwargs):
        print ("[INFO]: now exe {}()".format(func.__name__))
        return func(*args, **kwargs)
    return wrapper
    
@foo
def hello(x):
    print ("hello {}!".format(x))
    
hello("world")

解釋:

裝飾器等於修改了原函數定義,返回的仍然是函數定義!而不是單純的返回的函數運行結果。

此時再調用被裝飾函數實際執行的是已經被裝飾過的函數(即可以理解爲調用具有裝飾器的函數,該函數的實際定義已經不是你看到的定義,而是被裝飾器修改後的)

一次定義後即可重複使用,就像普通定義函數一般。

個人以爲如果用裝飾器,又不嵌套的寫法是完全有悖裝飾器初衷的,這時大可不必用裝飾器,還不如直接函數調用來的實在。

更多

如果對裝飾器不甚瞭解或者想了解更多,推薦下面的鏈接:爲什麼需要裝飾器

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章