复制-Python中的浅层复制和深层复制操作

在Python中,变量只是对对象的引用。因此,当将其分配给另一个变量时,它不会复制该对象,而是充当对同一对象的另一个引用。可以通过使用id()函数来验证

>>> L1 = [1,2,3]
>>> L2 = L1
>>> id(L1), id(L2)
(2165544063496, 2165544063496)

上面代码的结果表明,id()对于两个列表对象来说都是相同的,这意味着它们都引用相同的对象。据说L2是L1的浅表副本。由于两者都引用相同的对象,因此任何一个更改都将反映在另一个对象中。

>>> L1 = [1,2,3]
>>> L2 = L1
>>> L2[1] = 100
>>> L1,L2
([1, 100, 3], [1, 100, 3])

在上面的示例中,索引号为的项目 L2中的1被更改。我们看到两者都出现了这种变化。

当通过复制操作创建一个全新的对象时,嵌套对象的副本也会被递归添加到该对象中,该副本称为深层副本。

Python标准库的复制模块提供了两种方法:

  • copy.copy()–创建一个浅表副本

  • copy.deepcopy()–创建一个深拷贝

浅表副本会创建一个新对象,并存储原始元素的引用,但不会创建嵌套对象的副本。它只是复制嵌套对象的引用。结果,复制过程不是递归的。

>>> import copy
>>> L1 = [[1,2,3], [4,5,6]]
>>> L2 = copy.copy(L1)
>>> L1,L2
([[1, 2, 3], [4, 5, 6]], [[1, 2, 3], [4, 5, 6]])
>>> L2.append([10,10,10])
>>> L1,L2
([[1, 2, 3], [4, 5, 6]], [[1, 2, 3], [4, 5, 6], [10, 10, 10]])

这里L1是一个嵌套列表,L2是其浅表副本。尽管对父级列表对象的引用已复制到L2中,但其嵌套元素未复制。因此,当我们向L2附加另一个列表时,它不会反映在L1中

但是,如果我们尝试修改子元素中的元素,则在两个列表中都会看到其效果

>>> L1 = [[1,2,3], [4,5,6]]
>>> L2 = copy.copy(L1)
>>> L1,L2
([[1, 2, 3], [4, 5, 6]], [[1, 2, 3], [4, 5, 6]])
>>> L2[1][0] = 100
>>> L1,L2
([[1, 2, 3], [100, 5, 6]], [[1, 2, 3], [100, 5, 6]])

但是,深层副本会创建一个新对象,并递归地添加原始元素中存在的嵌套对象的副本。

在以下示例中,L2是L2的深层副本。现在,如果我们更改内部列表的任何元素,则不会在其他列表中显示。

>>> L1 = [[1,2,3], [4,5,6]]
>>> L2 = copy.deepcopy(L1)
>>> L1,L2
([[1, 2, 3], [4, 5, 6]], [[1, 2, 3], [4, 5, 6]])
>>> L2[1][0] = 100
>>> L1,L2
([[1, 2, 3], [4, 5, 6]], [[1, 2, 3], [100, 5, 6]])

因此,深层复制的效果由输出验证。