在Python參考手冊此陳述的Resolution of Names部分:
[..]如果當前範圍是一個函數範圍和名稱是指一個局部變量還沒有被勢必會在其中所使用的名稱的點值,一個UnboundLocalError
引發異常[..]
這時候UnboundLocalError
發生在官方消息。如果您在CPython的字節碼與dis
生成的功能f
看看你可以看到它試圖從局部範圍加載名稱時,其價值甚至還沒有尚未設置:
>>> dis.dis(f)
3 0 LOAD_GLOBAL 0 (print)
3 LOAD_CONST 1 (1)
6 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
9 POP_TOP
4 10 LOAD_GLOBAL 0 (print)
13 LOAD_FAST 0 (a) # <-- this command
16 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
19 POP_TOP
5 20 LOAD_CONST 2 (20)
23 STORE_FAST 0 (a)
26 LOAD_CONST 0 (None)
29 RETURN_VALUE
,你可以看到名字'a'
由LOAD_FAST
命令的方式加載到堆棧:
13 LOAD_FAST 0 (a)
這是用來搶在功能本地變量的命令(名爲FAST
,由於它是相當快比從全球範圍加載LOAD_GLOBAL
)。
這與以前定義的全局名稱a
無關。這與CPython會假設你打得很好並且生成LOAD_FAST
以參考'a'
這一事實有關,因爲'a'
正在中被分配給(即作爲本地名稱)在函數體內部。
對於一個名稱進入,並沒有相應的分配功能,CPython中不產生LOAD_FAST
,而是與LOAD_GLOBAL
去,並着眼於全球範圍內:
>>> def g():
... print(b)
>>> dis.dis(g)
2 0 LOAD_GLOBAL 0 (print)
3 LOAD_GLOBAL 1 (b)
6 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
9 POP_TOP
10 LOAD_CONST 0 (None)
13 RETURN_VALUE
所以它出現在解釋提前讀取整個函數以確定是否使用a
進行分配。這是記錄在任何地方?除了檢查語法錯誤外,是否還有其他任何解釋器向前看的場合?
在下文中,參考手冊的複合語句部分陳述對於函數定義:
函數定義是一個可執行語句。它的執行將當前局部命名空間中的函數名稱綁定到函數對象(函數的可執行代碼的包裝器)。
具體而言,其所結合的名稱f
到包含經編譯的代碼,f.__code__
,即dis
prettifies我們的一個功能對象。
我想你會發現默認情況下python無法從函數內部訪問全局變量。你將不得不明確聲明你的意思是使用全局。 (btw不要使用全局變量)。 – quamrana
@quamrana不真實。如果您將作業移除到本地'a',代碼將打印'10'。 – 2rs2ts
對於它的價值,這不是特定於python 3,只是在python 2中測試,併發生相同的事情。 – 2rs2ts