編輯:我沒有做好解釋我的問題。我對關閉如何感到困惑,函數似乎記住了它以前的環境,但通過遞歸調用它似乎找到了名稱的更新值。裝飾遞歸函數
我的困惑通過Thomas Ballinger "Finding closure with closures" talk完美解決:一個可變的
範圍在定義被確定,可變值在執行被確定。
因此,無論是遞歸還是閉包,名稱的綁定都是在定義時定義的,但該值可以在之後進行更新。
原題:
裝飾上的遞歸函數工作,而無需任何額外的努力:
def debug(f):
def new_f(*args, **kwargs):
print('arguments:', *args, **kwargs)
return f(*args, **kwargs)
return new_f
@debug
def f(n):
if n > 1:
return f(n-1)*n # f refers to the decorated version!
else:
return 1
在蟒蛇什麼機制保證在線路f
return f(n-1)*n
點的f
裝飾版本,而不是到原版的?
我認爲一個函數在定義的時候會記住它的上下文(因此,使用閉包,內部函數可以使用來自外部函數的對象)。但是當定義f
時,修飾器還沒有被應用,所以f
裏面的功能f
是指永久的未修飾版本?顯然,我誤解了函數範圍/上下文規則中的某些內容,但是什麼?
更多的是缺乏使其指向其他任何地方的機制。請記住,'@ debug'只是用於定義函數的語法糖,然後調用'f = debug(f)',無論您在哪裏尋找'f',您現在都可以獲得裝飾版本。 – jonrsharpe