Python 深浅拷贝完全指南:赋值、copy 与 deepcopy
·
1. 赋值
创建一个新的变量名,指向同一个对象
注意:+=和=的区别
+= 是原地修改,原变量指向的对象不变。
= 是创建了新的对象,原变量指向新对象。
a = [1, 2]
b = a
a += [3] # 原地修改,等价于 a.extend([3])
print(b) # [1, 2, 3] -> b 变了
a = a + [4] # 创建了新列表赋值给 a,b 还指向旧列表 [1,2,3]
print(b) # [1, 2, 3] -> b 没变
2. 浅拷贝 copy.copy()
浅拷贝只复制最外层对象,内部仍然共享引用
a = [[1, 2], [3, 4]]
b = copy.copy(a)
b[0].append(99)
print(a) # [[1, 2, 99], [3, 4]]
b.append(5)
print(a) # [[1, 2, 99], [3, 4]]
print(id(a))
print(id(b))
print(id(a[0]))
print(id(b[0]))
a与b指向不一样的对象,他们的内存地址是不同的。
但浅拷贝不会拷贝内部的子对象,所以a[0]与b[0]的内存地址是相同的。

3. 深拷贝 copy.deepcopy()
深拷贝会递归复制所有层级,完全独立![![[Pasted image 20260421201741.png]]](https://i-blog.csdnimg.cn/direct/a0671296a6064bc1a5e341036b125730.png)
a = [[1, 2], [3, 4]]
b = copy.deepcopy(a)
b[0].append(99)
print(a) # [[1, 2], [3, 4]]
b.append(5)
print(a) # [[1, 2], [3, 4]]
print(id(a))
print(id(b))
print(id(a[0]))
print(id(b[0]))
深拷贝是从内存中开辟了完全不同的空间,a和b完全不同。
不管是a和b,还是a[0]和b[0],内存地址都不同。
4. 三者对比
| 操作 | 外层对象 | 内层对象 | 修改b.append(x)(外层) |
修改b[0][0](内层) |
|---|---|---|---|---|
| b = a | 不复制 | 不复制 | 影响 | 影响 |
| copy.copy(a) | 复制 | 不复制 | 不影响 | 影响 |
| copy.deepcopy(a) | 复制 | 复制 | 不影响 | 不影响 |
5. 更Pythonic
5.1. 一维列表
a = [1,2,3]
b = a[:] # 切片 浅拷贝
或者
b = list(a)
注意:多维切片依然是浅拷贝
a = [[1],[2]]
b = a[:] # 仍然是浅拷贝
5.2. 只想避免修改原数据
不需要用到deep copy,可以:
# 用不可变结构
a = tuple([1,2,3])
或者
# 函数内不修改参数
def process(data):
return [x * 2 for x in data]
等价于
def process(data):
new_list = []
for x in data:
new_list.append(x * 2)
return new_list
更多推荐



所有评论(0)