2014-02-17 61 views
3

內的全局變量在此代碼段工作:用Python函數

def taylorVazquez(fx,a,b,n,puntos): 

    puntosX = linspace(a,b,num=puntos) 
    aproxY = [] 
    puntosY = []  

    def toFloat(): 
     puntosX = [float(x) for x in puntosX] 
     aproxY = [float(y) for y in aproxY] 
     puntosY = [float(y) for y in puntosY] 

我收到錯誤消息:

UnboundLocalError: local variable 'puntosX' referenced before assignment

而且所以我知道另外兩個變量也會發生同樣的情況。我能做什麼是外部taylorVazquez的變量是我在內部函數中操作的變量,換言之,我希望賦值也適用於外部範圍

回答

2

只要您將值賦給給定範圍內的變量,該變量被假定爲該範圍的本地。根據您使用的Python,您需要使用非本地(Python 3)或使用參數傳遞值(Python 2)。

這裏是的Python 2

def toFloat(puntosX, aproxY, puntosY): # now the names of the enclosing function can be passed to the toFloat function 
    puntosX = [float(x) for x in puntosX] 
    aproxY = [float(y) for y in aproxY] 
    puntosY = [float(y) for y in puntosY] 

的Python 3

def toFloat(): 
    nonlocal puntosX, aproxY, puntosY # the names now refer to the enclosing scope rather than the local scope 
    puntosX = [float(x) for x in puntosX] 
    aproxY = [float(y) for y in aproxY] 
    puntosY = [float(y) for y in puntosY] 

global在這種情況下不工作,因爲你引用一個封閉的名字功能。

還有一件事,你可能試圖給封閉範圍中的名稱賦新值。您目前的策略不會奏效,因爲您正在爲最內層的函數中的這些名稱分配新對象。 (列表解析創建新列表。)如果您需要保留新值,則需要(例如)將這些值返回到封閉範圍並將原始名稱重新分配給新值。例如,在Python 2:

def taylorVazquez(fx,a,b,n,puntos): 
    puntosX = linspace(a,b,num=puntos) 
    aproxY = [] 
    puntosY = [] 

    def toFloat(puntosX, aproxY, puntosY): # now the names of the enclosing function can be passed to the toFloat function 
     puntosX = [float(x) for x in puntosX] 
     aproxY = [float(y) for y in aproxY] 
     puntosY = [float(y) for y in puntosY] 
     return puntosX, aproxY, puntosY 

    puntosX, aproxY, puntosY = toFloat(puntosX, aproxY, puntosY) # now you can reassign these names to the new values 

不像global,你不能分配新值這些名字,並讓他們保持封閉範圍。

1

你可以很好地訪問變量,這裏的問題是,在Python2中沒有辦法重新分配變量。有一個PEP來解決這個問題(PEP-227)

它實際上解決在Python 3,你可以標記您的變量nonlocal,但是這不是如果你還在使用Python 2.一個巨大的安慰

你可以做這樣的事情解決它這樣的:

def f1(): 
    x = [1] 
     def f2(): 
     x[0] = 2 
    f2() 
    print x[0] 
f1() 

還有其他一些可能的解決辦法,但大多會導致意外的行爲。

2

如果您在Python函數中分配了一個變量,則解釋器會假定它是一個局部變量。該變量的所有其他用途也被假定爲本地的,即使是在賦值之前。這就是爲什麼你會得到一個關於local variable 'puntosX' referenced before assignment的例外。

有幾種可能的解決方案。

一種是聲明變量爲global(或在Python 3,nonlocal中,如果它是一個封閉函數中的局部變量)。

def taylorVazquez(fx,a,b,n,puntos): 

    puntosX = linspace(a,b,num=puntos) 
    aproxY = [] 
    puntosY = []  

    def toFloat(): 
     nonlocal puntosX, aproxY, puntosY # this fixes the UnboundLocalError 

     puntosX = [float(x) for x in puntosX] 
     aproxY = [float(y) for y in aproxY] 
     puntosY = [float(y) for y in puntosY] 

另一種選擇是對變量進行變異而不是重新賦值。例如,您可以在列表中使用list.appendlist.__setitem__,而無需對其進行本地引用。

def toFloat(): 
    for i, v in enumerate(puntosX): 
     puntosX[i] = float(v) # this calls puntosX.__setitem__, mutating it in place 

    # etc... 

最後一個選項是UNNEST的功能,並通過參數和返回值,而不是依賴於嵌套的命名空間,從而使您的值。例如:

def toFloat(lst): 
    return [float(v) for v in lst] 

# then later 
puntosX = toFloat(puntosX)