Python中的copy和deepcopy函数区别解析
Python中的copy和deepcopy函数是用来复制内存中的数据结构的函数。但是在Python中,由于变量引用的机制,复制一个对象并不是简单的复制,而是复制它的引用。因此,copy和deepcopy函数就出现了。
copy函数仅仅是复制了一层,如果原对象中有嵌套的其他对象,那么复制出来的新对象也只是一层复制。这就意味着,原对象和复制出来的对象会共享一个子对象的引用,这也就是Python中所说的浅拷贝。
而deepcopy函数则是完全复制了对象的所有层级。无论原对象有多少层嵌套,新对象都是全新生成的,它们之间互不影响。
下面我们通过几个例子来具体解析一下两个函数的区别。
例1:复制可变类型对象
我们首先来看一个复制可变类型对象的例子。
import copy
# 1. 原始列表对象
lst = [1, 2, [3, 4]]
# 2. 浅复制一个新的列表对象
new_lst = copy.copy(lst)
# 3. 深复制一个新的列表对象
deep_lst = copy.deepcopy(lst)
# 4. 修改原始列表对象中嵌套的列表对象
lst[2][0] = 5
# 5. 输出原始列表对象,新列表对象和深复制的列表对象
print(lst) # [1, 2, [5, 4]]
print(new_lst) # [1, 2, [5, 4]]
print(deep_lst) # [1, 2, [3, 4]]
结果分析:
首先,我们创建了一个原始列表对象lst,其中包含了一个嵌套的列表[3, 4]。然后,我们使用copy和deepcopy函数分别对它进行了复制。
然后,我们修改了原始列表对象lst中嵌套的列表[3,4]的 个元素,将其修改为5。最后,我们比较了原始列表对象lst、浅复制出来的新列表对象new_lst以及深复制出来的列表对象deep_lst,看看它们之间有什么区别。
由于lst和new_lst都是浅拷贝出来的,因此它们共享了[3, 4]这个子对象的引用。所以,当我们修改了lst中的[3, 4]的子对象时,new_lst的引用也会随之改变,导致它们输出结果完全相同。
而deep_lst则是深拷贝出来的,所以它和原始列表对象lst毫无关系,修改原始列表对象lst的操作并不会影响到它。
例2:复制不可变类型对象
接下来,我们来看一个复制不可变类型对象的例子。
import copy
# 1. 原始元组对象
tup = (1, 2, [3, 4])
# 2. 浅复制一个新的元组对象
new_tup = copy.copy(tup)
# 3. 深复制一个新的元组对象
deep_tup = copy.deepcopy(tup)
# 4. 修改原始元组对象中嵌套的列表对象
tup[2][0] = 5
# 5. 输出原始元组对象,新元组对象和深复制的元组对象
print(tup) # (1, 2, [5, 4])
print(new_tup) # (1, 2, [5, 4])
print(deep_tup) # (1, 2, [3, 4])
结果分析:
与之前不同的是,我们这里使用了一个元组对象作为原始对象进行复制。元组对象是Python中的不可变类型对象,因此我们无法修改元组内部的元素,只能对其中一个列表对象进行修改。
实际上,元组对象的浅复制和深复制与前面列表对象的测试结果是一样的。这是因为,元组对象内的可变类型子对象依然可以被修改,因此浅复制产生的新元组对象与原始元组对象的关系与浅复制列表对象的关系是一样的。
总结:
通过上述例子的分析,我们可以总结出以下结论:
copy和deepcopy函数的区别在于,前者进行的是浅复制,而后者进行的是深复制。
对于可变类型对象,浅复制出来的新对象和原始对象之间共享可变类型子对象的引用;而深复制出来的新对象是全新生成的。
对于不可变类型对象,浅复制和深复制的结果一样,因为不可变类型对象内部的可变类型子对象依然是可变的。
