2013-06-04 51 views
1

我使用Python的*創建一個默認值爲0的2-dimetion列表[[0] * 10] * 10。但是,當我將第一個元素設置爲1時,第一個列的所有元素都會發生1,爲什麼呢?Python的*操作符是如何工作的?

使用append創建列表時不會發生這種情況(請參閱下面的變量數據)。

#!/bin/env python 
#encoding=utf8 

width = 10 
height = 10 

data = [] 
for i in xrange(width): 
    data.append([0 for j in xrange(height)]) 

data2 = [[0]*width]*height 

print "before:",data == data2 
data[0][0] = 1 
data2[0][0] = 1 
print "after:",data == data2 

print "actually:" 
print data 
print data2 

輸出:

before: True 
after: False 
actually: 
[[1, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]] 
[[1, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0]] 

回答

1

列表中的*運算符將重複列表中的對象。但它並沒有使對象的副本重複實際的對象本身。

這個區別很微妙,很多時候你都不會注意到它。如果對象是不可變的,例如數字或字符串,則只需將對象替換爲不同的對象,然後列表中的成員將不再是同一個對象。

當列表中的對象可以被修改時,例如另一個列表,該對象的任何修改都將反映在列表中的所有其他重複引用中。

有一個尷尬的解決方法:

data3 = [[0]*width for i in range(height)] 
0

這裏:

[[0]*width] 

你只能創建一個列表[0],然後創建一個包含width引用到單個對象另一個列表。關鍵是*運營商只評估一次它的操作數。

這裏:

for i in xrange(width): 
    data.append([0 for j in xrange(height)]) 

要創建在每次迭代,你再追加一個新的列表。