2012-10-01 129 views
1

任何人都可以解釋下面的代碼異常。它只在將display()中的var sub更改爲另一個名稱時才起作用。也沒有全局變量sub。所以發生了什麼事 ?Python中的UnboundLocalError令人困惑

def sub(a, b): 
    return a - b 

def display(): 
    sub = sub(2,1) // if change to sub1 or sth different to sub, it works 
    print sub 
+0

最初,'sub'是一個函數。然後,它成爲函數的返回值。所以當你說'print sub'時,python不知道你指的是哪個'sub' – inspectorG4dget

+0

@ inspectorG4dget:你的解釋非常簡單。謝謝 –

回答

1

這是最初的評論。 OP發現這個有用的答案。因此,我將其重新發布爲答案

最初,sub是一個函數。然後,它成爲函數的返回值。所以當你說print sub時,python不知道你指的是哪一個sub

編輯

首先定義一個函數sub。現在,Python知道什麼sub是。

當您創建一個變量並嘗試分配給它(比如x = 2)時,python會評估=右側的內容,並將評估值指定爲左側內容的值的=。因此,右邊的所有內容都應該實際計算。

所以如果你的陳述是x = x+1,那麼x更好的是在該行之前賦值給它;並且之前定義的x必須是與1的添加兼容的某種類型。

但是,假設x是一個函數,你犯了一個在其他一些函數調用x變量,並試圖給它,使用功能x計算的值,那麼這真的開始迷惑蟒蛇哪些x你是指至。這是真的this answer過於簡單化了,這很好地解釋變量的作用域和Python函數陰影的一個更好的工作

+3

這太簡單了 - 如果你在'display'裏面說'sub = 1',你仍然會隱藏函數名,這是完全合法的。問題在於,在相同範圍內名稱被* used *和*分配給*。請參閱[本答案](http://stackoverflow.com/a/12092094/1110381)瞭解關於python中閉包的更詳細說明。 – l4mpi

+0

@ l4mpi:夠公平的。我真的應該在星期一早上停止回答問題,然後再開始我的咖啡。謝謝你的澄清 – inspectorG4dget

-1

的Python開始執行代碼,並得到了功能第一

def sub(a, b): 
    return a - b 

所以執行這個解釋得到後作爲函數的sub。現在,當走到下一行就發現

def display(): 
    sub = sub(2,1) // if change to sub1 or sth different to sub, it works 
    print sub 

所以第一線sub = sub (2, 1)sub功能轉換爲sub變量。從這個函數返回sub變量。所以它造成的問題。

+3

這完全不是發生了什麼... – l4mpi

2

任何變量分配給內部的範圍被視爲一個局部變量(除非聲明它global,或者,在python3,nonlocal),這意味着它在周邊範圍不查找。

一個簡單的例子用了同樣的錯誤:

def a(): pass 

def b(): a = a() 

現在,考慮在這裏所涉及的不同範圍:

全局命名空間包含ab

函數a不包含局部變量。

功能b包含一個分配給a - 這意味着它被解釋爲一個局部變量和陰影從外範圍的函數a(在這種情況下,在全球範圍內)。由於在調用之前尚未在b內定義a,所以它是一個未綁定的局部變量,因此是UnboundLocalError。這是完全一樣的,如果你這樣寫的:

def b(): x = x() 

這個解決方案很簡單:爲sub調用的結果選擇一個不同的名稱。

def display(): 
    value = sub(2,1)   #UnboundLocalError here... 
    print value 
    sub = "someOtherValue" #because you assign a variable named `sub` here 

這是因爲局部變量的列表是:錯誤本來還是發生了,如果你寫了這樣的功能 -

要注意,使用和分配的秩序並沒有區別是很重要的當python解釋器創建函數對象時生成。

+0

所以未綁定的錯誤來自對該函數的調用,因爲它先被前一個影子assignement?如果將x(局部變量)分配給任何值,然後調用x(函數),它是一樣的嗎? – njzk2

+0

錯誤在於你的函數包含一個'sub'的賦值,所以sub被視爲局部變量。並且您嘗試在初始分配期間使用此局部變量,但它尚未具有值。 – l4mpi

+0

非常感謝您的詳細解釋 – njzk2

1

對於使用的每個變量,Python都會確定它是本地變量還是非本地變量。引用未知變量將其標記爲非局部變量。之後重用相同的名稱作爲本地變量被認爲是程序員的錯誤。

考慮這個例子:

def err(): 
    print x # this line references x 
    x = 3 # this line creates a local variable x 
err() 

這給你

Traceback (most recent call last): 
    File "asd.py", line 5, in <module> 
    err() 
    File "asd.py", line 2, in err 
    print x # this line references x 
UnboundLocalError: local variable 'x' referenced before assignment 

會發生什麼情況基本上是Python的跟蹤到的代碼名稱的所有引用。當它讀取行print x Python知道x是來自外部作用域(upvalue或global)的變量。但是,在x = 3中,x被用作局部變量。由於這是代碼中的不一致,Python引發了一個UnboundLocalError以引起程序員的注意。