2016-03-10 55 views
1

似乎h [:] = h + 1且h = h + 1全部給h中的所有元素加1。numpy array,h [:] = h + 1 vs. h = h + 1

但是可能會在下面找到差異,你能解釋爲什麼嗎?看起來像在第二種情況下,h不僅變化爲函數內部變量,而且像覆蓋全局變量h一樣...這太混亂了...... 感謝您的任何輸入!

import numpy as np 

def fun(h): 
    h=h+1 
    return h 

h=np.zeros((2,2))+1 
hI=h.copy() 

for i in range(0,3):   
    hI = fun(h) 

print h 
print hI 
[[ 1. 1.] 
[ 1. 1.]] 
[[ 2. 2.] 
[ 2. 2.]] 

import numpy as np 

def fun(h): 
    h[:]=h+1 
    return h 

h=np.zeros((2,2))+1 
hI=h.copy() 

for i in range(0,3):   
    hI = fun(h) 

print h 
print hI 

[[ 4. 4.] 
[ 4. 4.]] 
[[ 4. 4.] 
[ 4. 4.]] 

回答

1

這並不奇怪。我認爲你被使用函數fun命名變量h的事實感到困惑。但該變量的名稱並不重要,它是不是達到父範圍修改變量h ...而是,傳遞給fun的參數是名稱的東西,而不是副本它。因此fun內部的突變仍會影響被命名的對象(在這種情況下,該對象是全局作用域h數組)。

爲了更清楚地說明這一點,考慮下面的情況下,如果我所做的只是重新命名變量的fun裏面是z,而不是h ...但相同的結果發生。

In [14]: def fun(z): 
    ....:  z[:] = z + 1 
    ....:  return z 
    ....: 

In [15]: h = np.zeros((2,2)) + 1 

In [16]: for i in range(0, 3): 
    ....:  hI = fun(h) 
    ....:  

In [17]: print h 
[[ 4. 4.] 
[ 4. 4.]] 

In [18]: print hI 
[[ 4. 4.] 
[ 4. 4.]] 

在第一個例子中,內部變量沒有變異。分配

h = h + 1 

導致本地h(該h的功能範圍內)是一個名稱,從操作h + 1在創造了力所能及的事以前命名爲h對象的名稱函數範圍(例如傳入的參數)。

由於一個NumPy的陣列h導致陣列,該語句h = h + 1沒有變異h廣播操作h + 1 ...只是導致名義h指新的東西(h + 1)。

而在第二個例子中,

h[:] = h + 1 

是說,含量,無論對象的h命名被更新。

你可以像我這樣稱呼它z[:],沒關係。左側的「thing [:]」是切片分配的符號,它是針對NumPy數組實現的,作爲切片對象數據的變形。

1

def fun(h): 
    h=h+1 
    return h 

使得輸入參數h的副本。所以輸入h從不改變,即使變量名稱碰巧是相同的(你可以使用f = h + 1; return f或者甚至return h + 1;所有的數量都相同)。當您將其分配給新的h時,您只會丟失對輸入h的引用。 由於輸入h碰巧是您的原始h(全1),原始文件永不改變,這是您在輸出中看到的內容。

每次添加1到原始數據(三個調用中的任意一個到fun),但由於原始數據不會更改,所以它始終是2的數組。

def fun(h): 
    h[:]=h+1 
    return h 

確實改變輸入h。憑藉[:],您可以將它「就地」更改。所以在這種情況下,返回的h與輸入h相同,這就是爲什麼您在輸出中看到相同的2x2數組的兩倍。
由於您正在運行此功能三次,它將被添加到它三次,導致所有的4。

1

區別在於對=聲明的解釋。所有這些都是there

案例h=h+1

如果目標是一個標識符(名字):名稱被綁定到當前局部名字空間的對象。

h[:]=h+1案例:

如果目標是一個訂閱:在參考的主要表達式,並且該序列被要求分配的對象分配給其與該索引項。