2015-05-15 52 views
3

爲什麼以下對象對[x] * n操作的行爲有所不同? 也就是說爲什麼第一個操作(in[94])修改了列表中的單個條目,而第二個操作(in[99])修改了全部是的條目?基本類型(int)與複雜類型(np.ndarray)之間的行爲差​​異

In [91]: x = 8 

In [92]: y = [x] * 10 

In [93]: y 
Out[93]: [8, 8, 8, 8, 8, 8, 8, 8, 8, 8] 

In [94]: y[1] = 4 

In [95]: y 
Out[95]: [8, 4, 8, 8, 8, 8, 8, 8, 8, 8] 

In [96]: x = np.zeros(shape=(3,3)) 

In [97]: y = [x] * 10 

In [98]: y 
Out[98]: 
[array([[ 0., 0., 0.], 
     [ 0., 0., 0.], 
     [ 0., 0., 0.]]), array([[ 0., 0., 0.], 
     [ 0., 0., 0.], 
     [ 0., 0., 0.]]), array([[ 0., 0., 0.], 
     [ 0., 0., 0.], 
     [ 0., 0., 0.]]), array([[ 0., 0., 0.], 
     [ 0., 0., 0.], 
     [ 0., 0., 0.]]), array([[ 0., 0., 0.], 
     [ 0., 0., 0.], 
     [ 0., 0., 0.]]), array([[ 0., 0., 0.], 
     [ 0., 0., 0.], 
     [ 0., 0., 0.]]), array([[ 0., 0., 0.], 
     [ 0., 0., 0.], 
     [ 0., 0., 0.]]), array([[ 0., 0., 0.], 
     [ 0., 0., 0.], 
     [ 0., 0., 0.]]), array([[ 0., 0., 0.], 
     [ 0., 0., 0.], 
     [ 0., 0., 0.]]), array([[ 0., 0., 0.], 
     [ 0., 0., 0.], 
     [ 0., 0., 0.]])] 

In [99]: y[1][1,2] = 5 

In [100]: y 
Out[100]: 
[array([[ 0., 0., 0.], 
     [ 0., 0., 5.], 
     [ 0., 0., 0.]]), array([[ 0., 0., 0.], 
     [ 0., 0., 5.], 
     [ 0., 0., 0.]]), array([[ 0., 0., 0.], 
     [ 0., 0., 5.], 
     [ 0., 0., 0.]]), array([[ 0., 0., 0.], 
     [ 0., 0., 5.], 
     [ 0., 0., 0.]]), array([[ 0., 0., 0.], 
     [ 0., 0., 5.], 
     [ 0., 0., 0.]]), array([[ 0., 0., 0.], 
     [ 0., 0., 5.], 
     [ 0., 0., 0.]]), array([[ 0., 0., 0.], 
     [ 0., 0., 5.], 
     [ 0., 0., 0.]]), array([[ 0., 0., 0.], 
     [ 0., 0., 5.], 
     [ 0., 0., 0.]]), array([[ 0., 0., 0.], 
     [ 0., 0., 5.], 
     [ 0., 0., 0.]]), array([[ 0., 0., 0.], 
     [ 0., 0., 5.], 
     [ 0., 0., 0.]])] 
+1

如果您複製了一個列表,例如,您將得到相同的行爲。 'X = [0,0,0]; Y = [X] * 4; Y [1] [1] = 2'。 – hpaulj

+0

所以這是關於複合類型的一般情況,而不是關於'np.ndarray'的具體內容。 – jgyou

+0

對,任何可變對象。只要你只是複製指針,修改一個都會修改它們。 – hpaulj

回答

2

TL;博士:你隱式地矩陣的shallow copy當你期待一個深拷貝。Documentation

考慮下面的代碼位:

In [38]: import numpy 

In [39]: a = numpy.eye(2) 

In [40]: a 
Out[40]: 
array([[ 1., 0.], 
     [ 0., 1.]]) 

In [41]: b = a 

In [42]: b 
Out[42]: 
array([[ 1., 0.], 
     [ 0., 1.]]) 

In [43]: a[0,0] = 2 

In [44]: a 
Out[44]: 
array([[ 2., 0.], 
     [ 0., 1.]]) 

In [45]: b 
Out[45]: 
array([[ 2., 0.], 
     [ 0., 1.]]) 

另外:

In [46]: id(a) 
Out[46]: 140529107552512 

In [47]: id(b) 
Out[47]: 140529107552512 

我定義a。設置b=a,然後更改a以找到b中的相同更改,即使我沒有觸碰b

按照你的線[x] * 10,它製作了10個淺拷貝x。所以,任何人的改變都會反映在其他人身上。

In [90]: x = np.zeros(shape=(3,3)) 
In [95]: y = [x] * 10 

In [96]: id(y[0]) 
Out[96]: 140529110575952 

In [97]: id(y[1]) 
Out[97]: 140529110575952 

In [98]: y[1][1,2] = 5 

In [99]: id(y[0]) 
Out[99]: 140529110575952 

In [100]: id(y[1]) 
Out[100]: 140529110575952 

這不是intany other non-compound type問題。

In [105]: x = 0 

In [106]: y = [x] * 10 

In [107]: y 
Out[107]: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] 

In [108]: y[1] = 2 

In [109]: y 
Out[109]: [0, 2, 0, 0, 0, 0, 0, 0, 0, 0] 

In [110]: id(y[0]) 
Out[110]: 140529069263200 

In [111]: id(y[1]) 
Out[111]: 140529069263152 
+1

不錯的偵探工作。 +1。 – rayryeng

+0

對。那麼這將意味着'[x] * n'調用淺拷貝「構造函數」n次?但是由於'int'只定義了深層複製,所以對象之間沒有引用。 – jgyou

+0

@JGab AFAIK,這正是發生了什麼。 – Nitish