在構建參數化裝飾器時,我還沒有意識到在Python中不允許在嵌套函數中傳遞參數的重新賦值。進一步看,我意識到這對簡單的功能也是如此。我演示已經降低到以下嵌套函數:在Python的函數調用中進行賦值嗎?
def a(s):
def b():
def c():
# nonlocal s # fix
print(s)
# while s:
# s -= 1 # uncommenting raises UnboundLocalError
print(s)
return None
return c()
return b()
a(3)
# 3
# 3
我想以下期望的輸出通過將評價while
循環:
a(3)
# 3
# 0
接着,在取消對while
環路的兩行給出出現以下錯誤,這表明將值重新分配給s
會產生錯誤:
<ipython-input-37-7141eb599936> in c()
3 def c():
4 # nonlocal s # fix
----> 5 print(s)
6 while s:
7 s -= 1 # uncommenting raises UnboundLocalError
UnboundLocalError: local variable 's' referenced before assignment
最後,取消註釋nonlocal
解決了此問題並提供了this post建議的所需輸出。
雖然問題解決了,但我想了解問題的根源。我注意到回溯點首次使用參數化參數s
(例如print(s)
),而不是指向實際導致錯誤的行(即while
循環/分配)。
我懷疑在調用函數時,Python首先會建立本地作用域的賦值。然後,分配的優先級高於或覆蓋來自外部作用域的繼承變量。因此,如果沒有對s
的分配,則使用外部s
。相比之下,在賦值時,在函數調用中重新定義s
,初始賦值之前的任何引用都會引發錯誤。這是正確的,還是有人可以解釋Python實際上在做什麼?
也許你可以看看Python如何使用http://www.pythontutor.com線逐行執行文件! – Windmill
@Windmill我很欣賞這個建議。他此刻,pythontutor顯示's'在'a()'的框架中可用,但它並不能清楚地表明在嵌套函數中's'是如何被觀察到的。 – pylang