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

pythonserver side programmingprogramming更新于 2023/12/23 4:12:00

在 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() –创建浅拷贝
  • 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]])

由此输出结果验证了深拷贝的效果。


相关文章