浅拷贝和深拷贝的区别

本文详细解释了浅拷贝与深拷贝的区别,包括它们如何处理基本数据类型和引用数据类型。浅拷贝仅复制对象的第一层属性,而深拷贝则递归复制所有层级的属性。

**

浅拷贝和深拷贝的区别**

基本数据类型:赋值,赋值之后两个变量互不影响
引用数据类型:赋址,两个变量具有相同的引用,指向同一个对象,相互之间有影响

什么是浅拷贝
创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值,如果属性是引用类型,拷贝的就是内存地址 ,所以如果其中一个对象改变了这个地址,就会影响到另一个对象。
在这里插入图片描述

什么是深拷贝
深拷贝会拷贝所有的属性,并拷贝属性指向的动态分配的内存。当对象和它所引用的对象一起拷贝时即发生深拷贝。深拷贝相比于浅拷贝速度较慢并且花销较大。拷贝前后两个对象互不影响。
在这里插入图片描述

浅拷贝(Shallow Copy)深拷贝(Deep Copy)是 Python 中复制复杂数据结构时的两种重要方式,它们的核心区别在于 **复制的“层次”深度不同**。 --- ## ✅ 一、核心定义 | 类型 | 定义 | |------|------| | **浅拷贝(Shallow Copy)** | 只复制对象的第一层,对于嵌套的可变对象(如列表、字典),仍然共享引用。 | | **深拷贝(Deep Copy)** | 递归地复制所有层级,完全独立,原对象新对象没有任何共享部分。 | --- ## ✅ 二、代码示例对比 ### 示例1:浅拷贝的问题(修改嵌套列表影响原对象) ```python import copy original = [[1, 2], [3, 4]] shallow_copy = copy.copy(original) # 或 original.copy() # 修改嵌套列表 shallow_copy[0].append(99) print("Original:", original) # [[1, 2, 99], [3, 4]] ❌ 被改变了! print("Shallow:", shallow_copy) # [[1, 2, 99], [3, 4]] ``` 👉 原因:`copy.copy()` 只复制了外层列表,里面的 `[1,2]` `[3,4]` 是**同一个对象**,所以修改会同步。 --- ### 示例2:深拷贝解决这个问题 ```python import copy original = [[1, 2], [3, 4]] deep_copy = copy.deepcopy(original) deep_copy[0].append(99) print("Original:", original) # [[1, 2], [3, 4]] ✅ 不受影响 print("Deep:", deep_copy) # [[1, 2, 99], [3, 4]] ``` 👉 `deepcopy` 会递归创建新的子对象,彻底隔离。 --- ## ✅ 三、内存图解说明 假设我们有: ```python original = [[1, 2], [3, 4]] ``` ### 浅拷贝后: ``` original ──→ [ ↗ , ↗ ] ←── shallow_copy ↓ ↓ [1,2] [3,4] ``` 两个列表都指向相同的子列表 → 修改子列表会影响彼此。 --- ### 深拷贝后: ``` original ──→ [ ↗ , ↗ ] ↓ ↓ [1,2] [3,4] deep_copy ─→ [ ↘ , ↘ ] ↓ ↓ [1,2] [3,4] ``` 所有层级都是独立的对象 → 完全隔离。 --- ## ✅ 四、哪些方法属于浅拷贝?哪些是深拷贝? | 方法 | 类型 | 说明 | |------|------|------| | `list.copy()` | 浅拷贝 | 只复制第一层 | | `list[:]` | 浅拷贝 | 切片也是浅拷贝 | | `list(lst)` | 浅拷贝 | 构造函数也是浅拷贝 | | `copy.copy(lst)` | 浅拷贝 | 显式调用 | | `copy.deepcopy(lst)` | ✅ 深拷贝 | 唯一能处理嵌套结构的安全方法 | --- ## ✅ 五、适用场景对比 | 场景 | 推荐拷贝方式 | |------|----------------| | 简单列表(只有数字、字符串等不可变元素) | 浅拷贝即可 | | 包含嵌套列表、字典、集合等可变对象 | 必须使用深拷贝 | | 自定义类实例的复制 | 通常需要 `deepcopy` | | 性能敏感且无嵌套 | 浅拷贝更快 | --- ## ✅ 六、特殊情况:不可变对象不需要深拷贝 ```python # 元组中的元素是不可变的,即使嵌套也不怕 t = ([1, 2], [3, 4]) import copy shallow = copy.copy(t) shallow[0].append(5) print(t) # ([1, 2, 5], [3, 4]) ❌ 还是被改了! # 所以即使是元组,只要里面是可变对象,也要 deepcopy deep = copy.deepcopy(t) ``` 📌 关键不是容器类型,而是**内容是否可变**。 --- ## ✅ 七、性能与开销 - **浅拷贝**:速度快,内存占用小。 - **深拷贝**:慢,尤其是大数据结构或深层嵌套时,因为要递归遍历每个对象。 > ⚠️ 注意:`deepcopy` 不能复制某些对象(如文件句柄、线程锁、lambda 函数等),可能报错或行为异常。 --- ## ✅ 八、如何验证是否真正独立? 你可以用 `id()` 查看对象地址: ```python import copy a = [[1, 2]] b = copy.copy(a) c = copy.deepcopy(a) print(id(a[0]) == id(b[0])) # True → 同一个对象(浅拷贝) print(id(a[0]) == id(c[0])) # False → 不同对象(深拷贝) ``` ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值