2013-10-25 62 views
6

在numpy的切片我用一些計算numpy的陣列,並發現了一個奇怪的問題,比如,假設我已經進口numpy.arange在IPython中,我運行一些腳本如下:陣列今天

In [5]: foo = arange(10)              

In [8]: foo1 = foo[arange(3)]             

In [11]: foo1[:] = 0               

In [12]: foo 
Out[12]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) 

In [16]: foo2 = foo[0:3]              

In [19]: foo2[:]=0                

In [21]: foo 
Out[21]: array([0, 0, 0, 3, 4, 5, 6, 7, 8, 9]) 

上面顯示當我通過foo [arange(3)]切片數組時,我獲得了數組切片的副本,但是當我通過foo [0:3]切片數組時,我得到了數組切片的引用,因此foo隨foo2而變化。後來我想foo​​和foo2的應該有相同的ID,但似乎並非如此

In [59]: id(foo) 
Out[59]: 27502608 

In [60]: id(foo2) 
Out[60]: 28866880 

In [61]: id(foo[0]) 
Out[61]: 38796768 

In [62]: id(foo2[0]) 
Out[62]: 38813248 

... 

就更奇怪了,如果我繼續檢查foo和foo2的的ID,他們不是恆定的,有時候,他們做了相互匹配!

In [65]: id(foo2[0]) 
Out[65]: 38928592 

In [66]: id(foo[0])               
Out[66]: 37111504 

In [67]: id(foo[0]) 
Out[67]: 38928592 

任何人都可以解釋這一點嗎?我真的蟒蛇的這種動態特徵混淆

非常感謝

回答

5
foo[arange(3)] 

不是一個切片。 arange(3)的元素用於選擇foo的元素來構造一個新的數組。由於這不能有效地返回視圖(視圖的每個元素必須是獨立的引用,並且視圖上的操作需要跟隨太多的指針),它會返回一個新的數組。

foo[0:3] 

是切片。作爲一種觀點,這可以高效地完成;它只需要調整一些邊界。因此,它返回一個視圖。

id(foo[0]) 

foo[0]不是指一個特定的Python對象。爲每個數組元素保留單獨的Python對象將會非常昂貴,否定了numpy的許多好處。相反,當在numpy ndarray上執行索引操作時,numpy將構造一個新對象以返回。每次你都會得到一個不同ID的對象。

+0

那麼,爲什麼id(foo)也不同於id(foo2)?他們是否使用第一個元素的地址作爲他們的地址? – shelper

+1

@shelper:foo不是foo2。儘管它們具有相同的形狀,dtype等,雖然它們對於它們的元素使用相同的存儲,但它們是不同的對象。我不認爲你收到的ID與數組元素的地址有任何關係;它是包含數組元數據的頭的地址和指向用於元素的存儲的指針。 – user2357112

+1

好吧,我想我明白這個問題,foo和foo2都是很好的包裝python對象,id(foo)只是顯示python對象的地址,而不是包含數據的內存,實際上可以通過「foo」獲取。 __array_interface __ ['data']「 – shelper