让我们从头开始,深入探索一下:
所以假设你有两个列表:
list_1=['01','98']
list_2=[['01','98']]
我们必须复制两个列表,现在从第一个列表开始:
那么首先,让我们尝试一下一般的复制方法:
copy=list_1
现在,如果您认为复制了 list_1,那么您可能是错的,让我们检查一下:
The id() function shows us that both variables point to the same list object, i.e. they share this object.
print(id(copy))
print(id(list_1))
输出:
4329485320
4329485320
惊讶吗?好的,让我们来探索一下:
所以我们知道python不会在变量中存储任何东西,变量只是引用对象,对象存储值。这里的对象是list,但是我们用两个不同的变量名创建了对同一个对象的两个引用。所以两个变量都指向同一个对象:
所以当您执行copy=list_1 时,它实际上在做什么:
在图像中,list_1 和副本是两个变量名,但两个变量的对象相同,即 list
因此,如果您尝试修改复制的列表,那么它也会修改原始列表,因为该列表只有一个,无论您是从复制的列表还是从原始列表进行修改,您都将修改该列表:
copy[0]="modify"
print(copy)
print(list_1)
输出:
['modify', '98']
['modify', '98']
所以它修改了原来的列表:
那么解决办法是什么?
解决方案:
现在让我们转向第二种复制列表的pythonic方法:
copy_1=list_1[:]
现在这个方法解决了我们在第一个问题中遇到的问题,让我们检查一下:
print(id(copy_1))
print(id(list_1))
4338792136
4338791432
所以我们可以看到我们的两个列表都有不同的 id,这意味着两个变量都指向不同的对象,所以这里实际发生的是:
现在让我们尝试修改列表,看看我们是否仍然面临之前的问题:
copy_1[0]="modify"
print(list_1)
print(copy_1)
输出:
['01', '98']
['modify', '98']
所以你可以看到它没有修改原始列表,它只是修改了复制的列表,所以我们可以接受。
所以现在我想我们已经完成了?等等,我们也必须复制第二个嵌套列表,所以让我们尝试一下 pythonic 方式:
copy_2=list_2[:]
所以 list_2 应该引用另一个作为 list_2 副本的对象让我们检查一下:
print(id((list_2)),id(copy_2))
我们得到输出:
4330403592 4330403528
现在我们可以假设两个列表都指向不同的对象,所以现在让我们尝试修改它,看看它是否给出了我们想要的:
所以当我们尝试时:
copy_2[0][1]="modify"
print(list_2,copy_2)
它给了我们输出:
[['01', 'modify']] [['01', 'modify']]
现在,这有点令人困惑,我们使用了 pythonic 方式,但我们仍然面临同样的问题。
让我们理解它:
所以当我们这样做时:
copy_2=list_2[:]
我们实际上只复制了外部列表,而不是嵌套列表,所以嵌套列表对于两个列表来说是同一个对象,让我们检查一下:
print(id(copy_2[0]))
print(id(list_2[0]))
输出:
4329485832
4329485832
所以实际上当我们执行copy_2=list_2[:] 时会发生这种情况:
它创建列表的副本,但只创建外部列表副本,而不是嵌套列表副本,嵌套列表对于两个变量都是相同的,因此如果您尝试修改嵌套列表,那么它也会修改原始列表,因为嵌套列表对象是两个嵌套列表相同。
那么解决办法是什么?
解决方案是deep copy
from copy import deepcopy
deep=deepcopy(list_2)
所以现在让我们检查一下:
print(id((list_2)),id(deep))
输出:
4322146056 4322148040
两个id都不一样,现在我们来看看嵌套列表id:
print(id(deep[0]))
print(id(list_2[0]))
输出:
4322145992
4322145800
如您所见,两个 id 不同,因此我们可以假设两个嵌套列表现在都指向不同的对象。
所以当您执行deep=deepcopy(list_2) 时,实际会发生什么:
所以两个嵌套列表都指向不同的对象,并且它们现在有单独的嵌套列表副本。
现在让我们尝试修改嵌套列表,看看它是否解决了之前的问题:
如果我们这样做:
deep[0][1]="modify"
print(list_2,deep)
输出:
[['01', '98']] [['01', 'modify']]
所以,如您所见,它没有修改原始嵌套列表,它只修改了复制的列表。