2014-01-09 57 views
0

Hello Python/iPython用戶。a = b似乎是相同的,而不是副本。爲什麼?

我發現了Python使用numpy數組的奇怪行爲。我自己找到了解決問題的辦法,但我很想得到解釋。提前致謝。

這裏的問題: 使用IPython中創建一個numpy的陣列和一個副本,稱爲B:

import numpy as np 
a=np.zeros(5) 
b=a 

然而,B似乎是相當的身份,而不是一個副本,因爲改變b也會改變。

b[0]=1 
a 
array([ 1., 0., 0., 0., 0.]) 

的解決方案是使用b=a.copy()而非b=a,但我想明白爲什麼這是蟒蛇的情況。我對Matlab,R和Fortran非常熟悉,從未遇到過這樣的問題。爲什麼有人想爲同一個數據取一個名字而不是這個向量的副本?只是一些python特定的語法的東西,還是有更多的理解?

+0

如果你想真正瞭解這裏發生了什麼,讀(http://nedbatchelder.com/text/names.html)由斯內德爾德[關於Python的名稱和值事實與神話。 –

回答

4

它只是一個python約定。所有的賦值都不會做任何事情,只是爲現有的對象創建一個新的句柄。這是一個非常明智的規則,因爲它使語義簡單而透明。在其他語言中,您可能經常會想知道您是修改現有對象還是創建一個新句柄。如果你想要做的不是在現有對象上打一個新名字,python總是強迫你做出明確的表示。至於你爲什麼要這樣做:試着找到任何一段python代碼,看看它包含了多少賦值語句。顯然有它的用途;)。

-1

這確實是python中一些對象的特殊性。 numpy數組實際上是從python的「list」對象派生出來的,它的作用方式與此相同。

實際上,當您在python(或一個numpy數組)中創建一個列表時,數據存儲在內存中的給定位置。 的標識號被關聯到該位置,並且可以使用該函數「ID」

a = [1, 2, 3] 
print id(a) 

如果鍵入「B = A」看到它,B將朝向相同的存儲單元的一個點。因此a和b將具有相同的 識別號碼。

a = [1, 2, 3] 
print id(a) 
b = a 
print id(b) 

你必須非常小心,因爲任何對will的修改都會影響b。 「複製」方法將創建的一個深拷貝,這意味着30b存儲到一個新的存儲位置

a = numpy.array([1, 2, 3]) 
print id(a) 
b = a 
print id(b) 
c = a.copy() 
print id(c) 

有相當於現在的「複製」的名單,而不是必須使用「:」符號

a = [1, 2, 3] 
print id(a) 
b = a 
print id(b) #a and b are the same 
c = a[:] 
print id(c) #c is a deep copy of a 
+0

你最後的評論'c是一個深的副本'是錯誤的:c只是一個淺拷貝(所以任何子列表都是原件而不是副本)。如果你想要一個深拷貝,使用'from copy import deepcopy'然後'c = deepcopy(a)'。有多種複製列表的方法:'c = list(a)'產生一個淺表副本,它總是一個列表,但是可以處理任何包括髮生器的序列,'c = a [:]'產生一個淺拷貝,與原始類型相同(例如,可以是'tuple'或'str'),但僅適用於可分片序列,並支持函數copy.copy和copy.deepcopy。 – Duncan

+0

另外,numpy數組並不是從Python列表派生的。 'ndarray.copy()'也不會創建深層副本。 –

相關問題