为了账号安全,请及时绑定邮箱和手机立即绑定

在Python中初始化2D列表:如何制作每一行的深层副本?

在Python中初始化2D列表:如何制作每一行的深层副本?

开心每一天1111 2021-03-27 19:15:32
假设我想用全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, 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]]那是怎么回事?为什么要对内部列表进行深层复制,而对外部列表进行浅层复制?
查看完整描述

3 回答

?
汪汪一只猫

TA贡献1898条经验 获得超8个赞

这样做 [[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)


查看完整回答
反对 回复 2021-04-01
?
四季花海

TA贡献1811条经验 获得超5个赞

该列表test包含同一列表的多个迭代,因此一个更改(如您通过重新分配的第一个元素所做的更改test[0])将反映在所有其他更改中。尝试以下方法:

[[0.0]*10 for _ in xrange(10)]  # or `range` in Python 3.x

当然,如果您只拥有,就不必担心这一点[0.0] * 10,因为这会创建一个整数列表,这些整数都无法改变。另一方面,列表确实是可变的。


查看完整回答
反对 回复 2021-04-01
  • 3 回答
  • 0 关注
  • 173 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信