2017-10-14 83 views
0

我正在使用Python 2.7.12和numpy 1.12.0並觀察以下行爲。這是預期的嗎?我假定「一個」是在範圍w.r.t在這兩種情況下「F2」如何被訪問「一個」比訪問不同[IND,:]奇怪的Python/numpy UnboundLocalError行爲

import numpy as np 
def f1(): 
    a = np.zeros((1, 10)) 
    def f2(): 
     print locals() 
     v = [0] * 10 
     v[3] = 1 
     a += v 
    f2() 


def f11(): 
    a = np.zeros((1, 10)) 
    def f2(): 
     print locals() 
     v = [0] * 10 
     v[3] = 1 
     a[0,:] = v 
    f2() 

結果::

>>> f11() 
{'a': array([[ 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]])} 
>>> f1() 
{} 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 8, in f1 
    File "<stdin>", line 7, in f2 
UnboundLocalError: local variable 'a' referenced before assignment 
>>> 
+1

你是*閱讀*和*分配給*'a'的'a + ='。這使得'a * a * local *變量,但直到它被分配後才能讀取它。在'f11()'中,你正在分配一個* slice *,這意味着'a'本身沒有被綁定,並且將它作爲閉包。 –

+0

@MartijnPieters那麼如何使用索引訪問工作? – vin

+1

使用索引進行訪問不會改變'a'指向的內容。它會要求'a'改變索引指向的內容,''''本身*相同,對數組對象的引用。 –

回答

1

在你的第一個例子,你用增量賦值

a += v 

這使得a一個局部變量;所有綁定操作(包括賦值)都使局部變量成爲可能。這是在編譯時確定的。請參閱Python執行模型的Naming and binding section

如果名稱在塊中被綁定,則它是該塊的局部變量。

[...]

下面的構造可以綁定名稱:[...]目標是標識符,如果在分配中,[...]發生。

a是一個標識符的目標。

因爲a被認爲是一個地方,試圖閱讀參考它已經綁定之前,將拋出一個異常UnboundLocal。增強作業必須先讀取a,然後才能將其分配回a,因此是例外情況。

你的第二個例子不綁定到af2;分配給切片a不會改變名稱a本身。您被分配到a[0,:];這不是一個標識符,這是一個切片。

您可以使用np.add(a, v, out=a)替代a += v來使第一個示例工作。

+1

不是'a.extend(v)',因爲'a'是一個NumPy數組,而不是一個列表。 'np.add(a,v,out = a)'應該可以工作。 – user2357112

+0

@ user2357112:啊,當然是廣播啊。 –

+0

@MartijnPieters還有一件事我不明白。請參閱編輯的問題。 在打印'locals()'f11在當地人中有一個,而f1不在 – vin