在Python中初始化2D列表:如何制作每行的深度副本?
假设我想用所有0初始化一个2D Python列表,我会执行如下操作:在Python中初始化2D列表:如何制作每行的深度副本?,python,Python,假设我想用所有0初始化一个2D Python列表,我会执行如下操作: test = [[0.0] * 10] * 10 然后我开始修改第一个列表中的值 test[0][0] = 1.0 但由于某些原因,这会影响所有列表的第一项: print test [[1.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, 0.0, 0.0, 0.0, 0.0, 0.0], [1.0, 0.0, 0.0,
test = [[0.0] * 10] * 10
然后我开始修改第一个列表中的值
test[0][0] = 1.0
但由于某些原因,这会影响所有列表的第一项:
print test
[[1.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, 0.0, 0.0, 0.0, 0.0, 0.0], [1.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, 0.0, 0.0, 0.0, 0.0, 0.0], [1.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, 0.0, 0.0, 0.0, 0.0, 0.0], [1.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, 0.0, 0.0, 0.0, 0.0, 0.0], [1.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, 0.0, 0.0, 0.0, 0.0, 0.0]]
这是怎么回事?为什么要制作内部列表的深层副本,而制作外部列表的浅层副本?执行
[[0.0]*10]*10
实际上会创建同一列表的多个副本,因此修改一个副本会影响所有副本:
>>> test = [[0.0] * 10] * 10
>>> [id(x) for x in test] #see all IDs are same
[3065020524L, 3065020524L, 3065020524L, 3065020524L, 3065020524L, 3065020524L, 3065020524L, 3065020524L, 3065020524L, 3065020524L]
试试这个:
>>> test = [[0.0]*10 for _ in xrange(10)]
>>> test[0][0] = 1.0
>>> test
[[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], [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.0]]
整数/浮点数是不可变的,而列表是可变的:
>>> x = y = []
>>> x is y # Both point to the same object
True
>>> x.append(1) # list.extend modifies a list in-place
>>> x,y # both references to [] can see the modification
([1], [1])
>>> x = y = 1
>>> x is y #both points to the same object
True
>>> x+=1 # only x gets modified, it now points to a new object 2
>>> x,y # y still points to the same object 1
(2, 1)
列表
test
包含同一列表的多个迭代,因此其中一个迭代的更改(正如您通过重新分配test[0]
的第一个元素所做的)会反映在所有其他列表中。请尝试以下方法:
[[0.0]*10 for _ in xrange(10)] # or `range` in Python 3.x
当然,如果您所拥有的只是
[0.0]*10
,那么您就不必担心这个问题,因为这会创建一个int列表,其中任何int都不会发生变异。另一方面,列表确实是可变的。真奇怪!我不明白为什么它会复制内部列表([0.0]*10
),而复制外部列表(([0.0]*10)*10
)[0.0]*10
创建[0.0,0.0,…]
。整数和浮点在python中是不可变的,因此即使此列表中的所有项都指向同一个对象0.0,但修改其中一项不会影响其他项,因为它们是不可变的。另一方面,列表是可变的,修改一个副本也会影响所有其他引用。