python中的浅拷贝和深拷贝
浅拷贝和深拷贝是 Python 中复制对象的两种方式,核心区别在于嵌套对象是复制引用还是递归复制。
| 概念 | 说明 | 嵌套对象关系 |
|---|---|---|
| 赋值 | 多个变量指向同一对象 | 完全共享 |
| 浅拷贝 | 复制外层容器,内层元素是引用 | 共享内层对象 |
| 深拷贝 | 递归复制所有层级 | 完全独立 |
二、赋值 vs 浅拷贝 vs 深拷贝
代码示例
import copy original = [[1, 2], [3, 4]] # 1. 赋值(只是新增一个引用) assigned = original # 2. 浅拷贝 shallow = copy.copy(original) # 3. 深拷贝 deep = copy.deepcopy(original) # 修改内层列表 original[0][0] = 99 print("原始:", original) # [[99, 2], [3, 4]] print("赋值:", assigned) # [[99, 2], [3, 4]] ← 受影响 print("浅拷贝:", shallow) # [[99, 2], [3, 4]] ← 受影响(内层共享) print("深拷贝:", deep) # [[1, 2], [3, 4]] ← 不受影响三、浅拷贝的实现方式
1. 使用copy.copy()
import copy original = [1, 2, [3, 4]] shallow = copy.copy(original)2. 使用切片[:]
original = [1, 2, [3, 4]] shallow = original[:]3. 使用list()构造函数
original = [1, 2, [3, 4]] shallow = list(original)4. 使用字典的copy()方法
original = {"a": 1, "b": [1, 2]} shallow = original.copy()四、深拷贝的实现方式
使用copy.deepcopy()
import copy original = [1, 2, [3, 4]] deep = copy.deepcopy(original) # 可选参数:指定哪些对象不需要深拷贝 deep = copy.deepcopy(original, memo={})自定义对象的深拷贝
import copy class Person: def __init__(self, name, friends): self.name = name self.friends = friends # 可选:自定义拷贝行为 def __copy__(self): """自定义浅拷贝""" return Person(self.name, self.friends) def __deepcopy__(self, memo): """自定义深拷贝""" new = Person(self.name, copy.deepcopy(self.friends, memo)) return new p1 = Person("Alice", ["Bob", "Charlie"]) p2 = copy.deepcopy(p1)五、不同数据类型的拷贝行为
1. 不可变类型(int, str, tuple)
import copy # 不可变类型:浅拷贝和深拷贝没有区别 a = (1, 2, [3, 4]) # 元组包含可变元素 shallow = copy.copy(a) deep = copy.deepcopy(a) # 注意:元组是不可变的,但内层列表是可变的 # 浅拷贝:内层列表是引用 # 深拷贝:内层列表是新对象2. 可变类型(list, dict, set)
import copy # 列表 lst = [1, 2, [3, 4]] shallow_lst = copy.copy(lst) # 内层列表共享 deep_lst = copy.deepcopy(lst) # 完全独立 # 字典 d = {"a": 1, "b": [1, 2]} shallow_d = copy.copy(d) # 内层列表共享 deep_d = copy.deepcopy(d) # 完全独立六、特殊类型的拷贝
1. 自定义类的拷贝
import copy class Address: def __init__(self, city): self.city = city class Person: def __init__(self, name, address): self.name = name self.address = address def __repr__(self): return f"Person({self.name}, {self.address.city})" addr = Address("北京") p1 = Person("Alice", addr) # 浅拷贝 p2 = copy.copy(p1) p2.address.city = "上海" print(p1) # Person(Alice, 上海) ← 受影响 # 深拷贝 p3 = copy.deepcopy(p1) p3.address.city = "广州" print(p1) # Person(Alice, 上海) ← 不受影响2. 循环引用的处理
import copy # 循环引用列表 lst = [] lst.append(lst) # 自己引用自己 # 深拷贝能正确处理循环引用 lst2 = copy.deepcopy(lst) print(lst2) # [...] 不会无限递归九、最后再来一个总表
| 操作 | 语法 | 外层容器 | 内层对象 | 适用场景 |
|---|---|---|---|---|
| 赋值 | b = a | 共享 | 共享 | 只需要别名 |
| 浅拷贝 | copy.copy(a) | 新对象 | 共享引用 | 嵌套结构简单 |
| 深拷贝 | copy.deepcopy(a) | 新对象 | 新对象 | 需要完全独立 |
备注:
浅拷贝只复制一层,内层对象是引用
深拷贝递归复制所有层,完全独立
不可变类型(int、str、tuple)的拷贝没有意义
深拷贝性能较差,非必要不使用
