在Python中将列表中的一个元素复制到列表中

4

将元素复制回列表中:

>> a = [[1,2],[3,4]]
>> b = []
>> b = a[1]
>> a.insert(1,b)
>> a
[[1,2],[3,4],[3,4]]
>> a[2][0] = 0
>> a
???

我应该期望列表'a'是什么?它的结果是[[1,2],[0,4],[0,4]],这让我非常惊讶,因为我预期的是[[1,2],[1,4],[0,4]]。
我有点知道答案,但是思路还不是很清晰。请详细告诉我为什么会发生这种情况以及如何解决它?

请阅读此链接:https://nedbatchelder.com/text/names.html - juanpa.arrivillaga
2
另外,b = [] 这一行是完全没有用的,因为你立即重新分配了 b... - juanpa.arrivillaga
通过执行 b = [],我试图在内存中为列表 b 分配空间。但是后来我发现了另一种方法,即 b = list(a[1]),它会为 b 创建一个新对象,而不仅仅是指向 a[1] 的指针。 - Sunal Mittal
1
它们在语义上是不同的。 - juanpa.arrivillaga
2个回答

6
b = a[1]
a.insert(1,b)

b是对a[1]的引用,因此在插入后修改引用时,由于其本质上指向相同的数据,因此会同时出现在两个位置。

如果要避免这种情况,请使用deepcopy

from copy import deepcopy

a = [[1,2],[3,4]]
b = []
b = deepcopy(a[1])
a.insert(1,b)
print(a) # prints [[1, 2], [3, 4], [3, 4]]
a[2][0] = 0
print(a) # prints [[1, 2], [3, 4], [0, 4]]

我认为 deepcopy(a[1]) 所做的与 list(a[1]) 的作用类似。 - Sunal Mittal
1
@SunalMittal 是的,请查看 https://docs.python.org/2/library/functions.html#func-list - PYA
1
但是请注意,copy.copy()、list[:]和list(list)与copy.deepcopy()及其Python版本不同,它们不会复制列表、字典和列表中的类实例,因此如果原始对象发生更改,则复制后的列表中也会相应发生更改,反之亦然。更多信息,请参见 https://dev59.com/XXE85IYBdhLWcg3wyGp_#2612990。 - PYA

3

原因是由于在Python中列表的工作方式,它们具有所谓的“链接数据”。如果您有一个指向列表中对象的实例,然后修改该对象,列表中的对象也会被修改,因为列表只是指向对象。所以:

x = [1,2]
b = [1,3]
x[0] = b
b[0] = 2

那么打印x将会得到[[2,3],2]而不是[[1,3],2]。

在你的情况中发生了这样的事情:你将a中位置1的对象设置为指针/变量b。然后将该指针插入a的位置2。因此,当你修改a的位置2时,也会修改b,从而修改a的位置1。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接