前言:
Python中的拷贝主要分为浅拷贝(shallow copy)和深拷贝(deep copy),它们在处理复杂对象(例如包含其他对象的对象)时的行为有明显差异。浅拷贝仅复制对象的第一层,而深拷贝则递归地复制对象的所有层级。理解这两种复制方法对于处理复杂的数据结构至关重要。
1 浅拷贝(Shallow Copy)
浅拷贝创建一个新对象,其内容是原对象中元素的引用。如果原对象中的元素是不可变的(比如整数、字符串和元组),那么这种区别几乎察觉不到,因为它们的值不会改变,仿佛是深拷贝。但如果对象包含可变对象(如列表,字典等),浅拷贝会导致原对象和拷贝对象中的可变元素指向同一对象。因此,修改任何一个对象中的可变元素,另一个对象也会受到影响。浅拷贝可以使用copy模块的copy()函数实现,也可以通过其他方式(如:使用切片操作复制列表)。
1.1 示例:
#!/usr/bin/env python
# coding=utf-8
"""
# @Time : 2024/4/6 8:25
# @Author : Summer
# @File : test.py
# @describe:
"""import copy# 原始列表
original_list = [1, 2, [3, 4]]# 使用copy模块的copy方法进行浅拷贝
shallow_copied_list = copy.copy(original_list)print("Original list ID:", id(original_list)) # 原列表的内存地址
print("Shallow Copied list ID:", id(shallow_copied_list)) # 浅拷贝列表的内存地址# 打印浅拷贝前后,嵌套列表的内存地址
print("Original list nested list ID:", id(original_list[2])) # 原列表中嵌套列表的内存地址
print("Shallow Copied list nested list ID:", id(shallow_copied_list[2])) # 浅拷贝列表中嵌套列表的内存地址# 输出
# Original list ID: 2347612655360
# Shallow Copied list ID: 2347612843904
# Original list nested list ID: 2347612840448
# Shallow Copied list nested list ID: 2347612840448
在浅拷贝的情况下,你会发现original_list和shallow_copied_list的内存地址是不同的,证明它们是不同的对象。然而,original_list[2]和shallow_copied_list[2](即嵌套列表的部分)的内存地址是一样的,说明浅拷贝只复制了最外层对象,内层的嵌套列表仍然是同一个对象。
2 深拷贝(Deep Copy)
深拷贝则不同,它创建一个新对象,并递归地复制原对象中的所有元素。如果原对象包含对其他对象的引用,深拷贝不仅会复制引用的对象的结构,也会复制引用的对象本身。这意味着原对象和副本之间不会相互影响。
深拷贝可以通过copy模块的deepcopy()函数实现,对于深拷贝,我们对同样的原始列表进行操作,并观察内存地址的变化。
2.1 示例
#!/usr/bin/env python
# coding=utf-8
"""
# @Time : 2024/4/6 8:25
# @Author : Summer
# @File : test.py
# @describe:
"""import copy
# 原始列表
original_list = [1, 2, [3, 4]]# 使用copy模块的deepcopy方法进行深拷贝
deep_copied_list = copy.deepcopy(original_list)print("Original list ID:", id(original_list)) # 原列表的内存地址
print("Deep Copied list ID:", id(deep_copied_list)) # 深拷贝列表的内存地址# 打印深拷贝前后,嵌套列表的内存地址
print("Original list nested list ID:", id(original_list[2])) # 原列表中嵌套列表的内存地址
print("Deep Copied list nested list ID:", id(deep_copied_list[2])) # 深拷贝列表中嵌套列表的内存地址# 输出
# Original list ID: 2293115743744
# Deep Copied list ID: 2293115924032
# Original list nested list ID: 2293115920576
# Deep Copied list nested list ID: 2293115920832
在深拷贝的情况下,original_list和deep_copied_list的内存地址不同,表示它们是不同的对象。与浅拷贝不同的是,嵌套列表original_list[2]和deep_copied_list[2]的内存地址也不相同。这表明深拷贝不仅复制了最外层的对象,还复制了里面所有层级的对象,由此可见每一层的元素都是独立的。
3 深、浅拷贝区别
浅拷贝 (Shallow Copy)
浅拷贝仅复制对象的顶层,如果该对象包含对其他对象的引用,这些引用将会被复制,但引用的对象本身不会被复制。
浅拷贝的结果是,原始对象和其副本共享内部嵌套的对象。这意味着如果你在副本中修改了嵌套对象,原始对象中的相应嵌套对象也会受到影响,反之亦然。
浅拷贝可以通过使用copy模块的copy()函数实现,也可以使用某些其他方法如列表的list()构造函数或切片操作[:]。
浅拷贝通常性能较好,因为它不需要复制嵌套的对象。
深拷贝 (Deep Copy)
深拷贝不仅复制对象的顶层,还会递归复制所有嵌套对象。这意味着它会创建所有原始对象中嵌套元素的副本。
深拷贝的结果是,副本与原始对象完全独立,对副本的修改不会影响到原始对象,反之亦然。
深拷贝可以使用copy模块的deepcopy()函数实现。
深拷贝由于需要复制所有嵌套的对象,所以性能开销相比浅拷贝要大。在处理大型复杂对象时,深拷贝可能会消耗大量的时间和内存。