在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]])
因此,深层复制的效果由输出验证。