所以,我正在玩Python试图学习如何使用它,我发现了一些奇怪的东西。我的代码是:
list1 = range(0, 2)
list2 = range(2, 4)
comb = list1, list2
print comb
print list1
list1.append(list2)
print comb
print list1
输出是:
print comb --- ([0, 1], [2, 3])
print list1 --- [0, 1]
print comb --- ([0, 1, [2, 3]], [2, 3])
print list1 --- [0, 1, [2, 3]]
似乎正在发生的事情是我将两个列表组合在一起,这很好。但是当我将list2
追加到list1
并重新打印我的comb
列表时,comb
列表已使用新添加的list1
更新。
我错过了什么?自comb
追加以来,list1
为什么没有重新计算时会发生变化?
答案 0 :(得分:2)
comb
包含引用到list1
和list2
本身,而不是它们的副本。此外,这意味着comb[0]
实际上是list1
和副作用。
以下是演示:
>>> list1 = range(0, 2)
>>> list2 = range(2, 4)
>>> comb = list1, list2
>>> id(list1)
28888960
>>> id(comb[0])
28888960
>>>
在上面的示例中,请注意list1
和comb[0]
的ID是如何相同的。这告诉你的是它们都引用了内存中的同一个对象。因此,当您更新一个时,另一个也将更新。
要解决此问题,请comb
包含list1
和list2
的副本,而不是参考:
>>> list1 = range(0, 2)
>>> list2 = range(2, 4)
>>> # [:] creates a shallow copy of the lists.
>>> comb = list1[:], list2[:]
>>> id(list1)
28930176
>>> id(comb[0])
28931696
>>>
如您所见,list1
和comb[0]
的ID现在不同了。这意味着它们不再引用同一个对象。
答案 1 :(得分:2)
comb
是一个元组,其中两个引用指向list1
和list2
名称所引用的相同列表对象。
将list2
添加到list1
后,您将该列表的另一个引用添加到list1
。现在您有 3 对该列表对象的引用。一个位于list2
,另一个位于comb[1]
,另一个位于list1[2]
。
每当您在Python中操作列表或字典或任何其他可变对象类型时,对该对象的所有引用都将反映这些更改,因为您只处理一个对象。
将图片对象作为气球,名称是标签,用线程绑定到气球上。线程是引用。你可以将多个标签绑在一个气球上,但你仍然只有一个气球,如果你弹出气球,所有的标签都会被绑在同一块无生命的橡胶上。
列表和元组只是带有编号标签的气球;这些标签与其他对象相关联。因此,comb
是一个带有两个标签的气球,编号为0和1.这些标签与相同气球list1
和list2
绑定< em>以及。
答案 2 :(得分:0)
comb
将引用保存到list1
和list2
。因此,当您更新list1
时,comb
也会更新。
如果您希望comb
保留list1
和list2
而非参考的数据副本,请尝试:
comb = (list1[:], list2[:])
答案 3 :(得分:0)
comb
由list1
和list2
组成。变异list1
不会改变这一点,而comb
似乎已经改变,但实际上它仍然完全相同。
答案 4 :(得分:0)
我的一位同事前几天有这个。这种效果源于你的
comb = list1, list2
您需要使用
comb = list(list1 + list2)
实际复制列表,参见http://www.precheur.org/python/copy_list和http://od-eon.com/blogs/bogdan/python-assignment-value-or-reference/