我有一个关于列表浅拷贝的问题。
在这两个示例中,我修改了列表中的一个元素,但在示例1中,列表b
已更改,而在示例2中,列表d
未更改。我很困惑因为在这两个例子中,我修改了列表的一个元素。
有什么区别?
示例1:
a=[1,2,[3,5],4]
b=list(a)
a[1]=0
print(a) # [1, 0, [3, 5], 4]
print(b) # [1, 2, [3, 5], 4]
示例2:
c=[1,2,[3,5],4]
d=list(c)
c[2][0]=0
print(c) # [1, 2, [0, 5], 4]
print(d) # [1, 2, [0, 5], 4]
答案 0 :(得分:3)
浅拷贝意味着您获得一个新列表但元素是相同的。因此,两个列表都具有相同的第一个元素,第二个元素等。
如果添加,删除或替换浅层复制列表中的值,则更改未反映在原始列表中(反之亦然),因为浅层副本创建了新列表。但是,如果您更改中的某个元素,则两个列表中都会显示更改,因为两个列表都引用相同的项目。因此,内部列表实际上在新列表和旧列表之间共享,如果您更改它,则两者都可以看到该更改。
请注意,您实际上没有更改任何一个示例中的元素,您在第一个示例中替换列表中的元素,而在第二个示例中,您替换列表元素的元素。
我目前正在使用graphviz,所以让我添加一些图片来说明这一点:
浅层拷贝意味着您获得了一个新列表,但列表中存储的对象是相同的:
如果替换其中任何一个元素,相应的元素将仅引用一个新项目(您的第一个示例)。看一个列表如何引用这两个列表,另一个列表引用零:
虽然对引用项目的更改将更改该项目,并且引用该项目的每个对象都将看到更改:
答案 1 :(得分:1)
[ 1。 =复制对象的引用,因此任一列表中的任何更改都会反映在另一个
中phpinfo
->做相同的工作。
也就是说,它仅复制单个对象的引用,例如b [0] = a [0]和b 2 = a 2,依此类推。使用int,string等,就好像x = 10和y = x并且更改'x'或'y'的值不会影响其他值一样。当您进行浅表复制时,a和b的其余元素会发生这种情况。因此,如在您的问题中使用浅拷贝进行b=list(a) or b=a.copy()
时的行为如上所述,因此更改不会同时反映在两个列表中。但是嵌套的列出列表就像b=list(a) and a[1]=0
和a=[1,2,3]
一样作为列表分配,使a 2 = 3也会将b 2更改为3,即a或b效果的变化两者(与上述情况1相同)。因此,这就是为什么在列表中包含列表的情况下,任何更改都会反映在两个列表中的原因。就像您在示例中进行b=a
一样(此处复制d=list(c)
时类似于列表分配,即复制了引用,并且在列表分配的情况下两者都反映出更改,因此对d {2的更改或c 2都反映在两个列表中),因此d[2]=c[2]
也会将d [2] [0]更改为零。
在http://www.pythontutor.com/visualize.html#mode=edit处尝试代码 更好地了解
c[2][0] = 0
答案 2 :(得分:0)
在这两个示例中,您将创建列表的浅表副本。浅拷贝基本上将别名复制到第一个列表中的所有元素到第二个列表。
因此您已将引用复制到[int, int, list, int]
。 int
元素是不可变的,但list
元素是可变的。所以第三个元素都指向Python内存中的同一个对象。修改该对象会修改对它的所有引用。