在 Python 中,复制对象是常见的操作,但复制的方式分为两种:浅拷贝和深拷贝。理解它们的区别对于避免程序中的意外行为至关重要。
浅拷贝 (Shallow Copy)
- 浅拷贝创建一个新对象,但该新对象包含的元素是对原始对象中元素的引用。这意味着,如果修改新对象中的元素,原始对象也会受到影响。
- 常用的浅拷贝方法:
- copy.copy() 函数
- 切片操作 [:]
- 赋值运算符 =(对于可变对象)
示例:
import copy
list1 = [1, 2, [3, 4]]
list2 = copy.copy(list1)
list2[2].append(5) # 修改 list2 中的嵌套列表
print(list1) # 输出: [1, 2, [3, 4, 5]] 原始列表也被修改了
print(list2) # 输出: [1, 2, [3, 4, 5]]
深拷贝 (Deep Copy)
- 深拷贝创建一个新对象,并递归地复制所有嵌套对象。这意味着,新对象和原始对象完全独立,修改新对象中的元素不会影响原始对象。
- 常用的深拷贝方法:
- copy.deepcopy() 函数
示例:
import copy
list1 = [1, 2, [3, 4]]
list2 = copy.deepcopy(list1)
list2[2].append(5) # 修改 list2 中的嵌套列表
print(list1) # 输出: [1, 2, [3, 4]] 原始列表不受影响
print(list2) # 输出: [1, 2, [3, 4, 5]]
如果上面的讲解你还是不太明白,我给你举一个生活中的例子:
想象你有一份美味的披萨,你想分享给你的朋友。复制披萨的方式有两种:
1. 浅拷贝:切片分享
-
你用刀将披萨切成两半,你和朋友一人一半。
-
如果你往你的那一半披萨上加了辣椒粉,那么你朋友的那一半也会有辣椒粉的味道,因为你们分享的是同一份披萨。
-
这就是浅拷贝:复制了披萨的结构(形状),但你们仍然共享着相同的披萨(数据)。
2. 深拷贝:重新做一份
-
你决定重新做一份完全一样的披萨给你朋友。
-
现在,你可以在你的披萨上加辣椒粉,而不会影响你朋友的披萨,因为你们拥有的是两份独立的披萨。
-
这就是深拷贝:不仅复制了披萨的结构,还复制了披萨本身(数据),创造了完全独立的副本。
什么时候使用哪种复制方式
-
浅拷贝:
-
如果你只是想分享披萨的形状(例如,记录披萨的大小),而不在乎配料是否相同,那么浅拷贝就足够了。
-
浅拷贝速度更快,因为不需要复制所有的配料。
-
-
深拷贝:
-
如果你想给你朋友一份完全独立的披萨,可以在上面添加不同的配料,那么你需要进行深拷贝。
-
深拷贝会复制所有的配料,因此速度会慢一些,但可以确保你朋友的披萨不受你的影响。
-
何时使用深拷贝或浅拷贝
- 浅拷贝: 适用于只需要复制对象结构,而不关心元素是否共享的情况。例如,创建对象的副本作为函数参数传递,避免修改原始对象。
- 深拷贝: 适用于需要创建完全独立的对象副本,修改副本不会影响原始对象的情况。例如,在多线程环境中,每个线程需要独立的对象副本,避免数据竞争。
总结
- 浅拷贝只复制对象的第一层,而深拷贝会递归复制所有嵌套对象。
- 使用浅拷贝时要注意,修改新对象中的元素可能会影响原始对象。
- 选择使用深拷贝还是浅拷贝取决于你的具体需求和场景。
写的这么干货,你确定不关注一下吗