搞清楚浅拷贝与深拷贝,再也不踩坑!
2023-11-15 10:36:38
在编程的世界里,"拷贝"是一个经常用到的操作,它能将一个对象复制一份出来。但在 Python 中,拷贝又分为"浅拷贝"和"深拷贝"两种类型,它们之间有微妙的区别,如果没理解清楚,用到了很可能会踩坑。
浅拷贝:复制"指针","指向"相同对象
浅拷贝,顾名思义,只拷贝了对象的引用(指针),即指向该对象内存地址的引用。也就是说,浅拷贝后的新对象与原对象指向了同一个内存地址,它们共用同一份数据。
为了方便理解,我们举个例子:
# 定义一个列表
list1 = [1, 2, 3]
# 浅拷贝列表
list2 = list1
此时,list2
就是list1
的浅拷贝,它们指向了同一块内存空间。
内存地址 | 内容
---------|--------
0x123456 | [1, 2, 3]
深拷贝:复制"值","创建"新对象
深拷贝,则拷贝了对象及其所有的子对象,创建了一个完全独立的新对象。也就是说,深拷贝后的新对象和原对象拥有不同的内存地址,它们不共用同一份数据。
继续上面的例子,我们对list1
进行深拷贝:
# 深拷贝列表
import copy
list3 = copy.deepcopy(list1)
此时,list3
就是list1
的深拷贝,它们拥有不同的内存地址。
内存地址 | 内容
---------|--------
0x123456 | [1, 2, 3]
0x654321 | [1, 2, 3]
区别总结
下表总结了浅拷贝和深拷贝的区别:
特征 | 浅拷贝 | 深拷贝 |
---|---|---|
指针 | 复制引用 | 复制值 |
内存地址 | 共用内存地址 | 创建新内存地址 |
更改影响 | 更改一个对象会影响另一个对象 | 更改一个对象不会影响另一个对象 |
实例对比
为了进一步理解,我们来看一个实际的例子。
假设我们有一个包含列表的字典:
my_dict = {
"list1": [1, 2, 3],
"list2": [4, 5, 6],
}
现在,我们分别对my_dict
进行浅拷贝和深拷贝:
# 浅拷贝字典
shallow_copy = my_dict
# 深拷贝字典
import copy
deep_copy = copy.deepcopy(my_dict)
此时,shallow_copy
和deep_copy
都是my_dict
的拷贝,但它们的行为不同。
如果我们修改shallow_copy
中list1
的值:
shallow_copy["list1"].append(4)
那么my_dict
中的list1
的值也会发生改变,这是因为shallow_copy
和my_dict
指向了同一块内存空间。
内存地址 | 内容
---------|--------
0x123456 | [1, 2, 3, 4]
而如果我们修改deep_copy
中list1
的值:
deep_copy["list1"].append(4)
那么my_dict
中的list1
的值不会发生改变,这是因为deep_copy
和my_dict
指向了不同的内存空间。
内存地址 | 内容
---------|--------
0x123456 | [1, 2, 3]
0x654321 | [1, 2, 3, 4]
使用场景
浅拷贝和深拷贝在不同的情况下都有各自的用途:
- 浅拷贝: 适用于对象本身的修改不会影响其他对象的情况,例如复制一个临时变量或只读数据。
- 深拷贝: 适用于对象本身的修改可能会影响其他对象的情况,例如复制一个包含其他对象的复杂对象。
结语
理解浅拷贝和深拷贝的区别对于写出健壮可靠的 Python 代码至关重要。下次再使用拷贝操作时,请花点时间考虑是需要浅拷贝还是深拷贝,这将有助于避免不必要的错误和坑点。