赋值b=a、浅拷贝copy.copy()、深拷贝copy.deepcopy()

浅拷贝与深拷贝详解
本文通过实例详细解析了Python中浅拷贝与深拷贝的区别,展示了如何使用copy模块来避免直接赋值导致的数据意外修改问题。

参考:
https://blog.youkuaiyun.com/shine_00/article/details/126092055
https://blog.youkuaiyun.com/Goodness2020/article/details/125919858

发现问题的契机:

# 如果直接val = true_val_pred[pos[i][1]:pos[i][3], pos[i][0]:pos[i][2]]
# 那么当true_val_pred[pos[i][1]:pos[i][3], pos[i][0]:pos[i][2]]改变时,如true_val_pred[pos[i][1]:pos[i][3], pos[i][0]:pos[i][2]] = Y_val_pred[i]
# val也会随之改变
# b=a是赋值语句,b指向a的地址,a和b任何一个改变了,另一个也跟着改变
# !!!如果想要val不变,则需要浅拷贝,val = true_val_pred[pos[i][1]:pos[i][3], pos[i][0]:pos[i][2]].copy()
# b=a.copy()是把a的值赋给b,a和b有不同的内存地址,一个改变了,另一个不变

!!!

  • 直接赋值:新变量直接引用原对象,任一对象改变,则所有指向了同一可变对象的变量都作相同改变。

  • 浅拷贝:使用 copy.copy() 函数实现,浅拷贝原变量指向的对象的最外层,但引用原变量指向的对象的内层。

  • 深拷贝:使用 copy.deepcopy() 函数实现,拷贝可变对象的最外层对象及子对象,新变量指向的和原变量指向的对象两者完全独立

import copy

a = [1, 2, [3, [4, 5]]]
b = a                 # 直接赋值: 引用对象,原始对象的最外层到最内层对象均被引用
c = copy.copy(a)          # 浅拷贝:原始对象的最外层对象深拷贝,除外层的所有层对象直接赋值
d = copy.deepcopy(a)  # 深拷贝,原始对象的最外层到最内层对象均不因原对象的改变而改变

a.append(6)
a[2].append(7)
a[2][1].append(8)

print("a:", a)
print("b:", b)
print("c:", c)
print("d:", d)
a: [1, 2, [3, [4, 5, 8], 7], 6]
b: [1, 2, [3, [4, 5, 8], 7], 6]
c: [1, 2, [3, [4, 5, 8], 7]]   
d: [1, 2, [3, [4, 5]]]
<think> 我们正在讨论的是Python中的`copy.deepcopy`函数,具体在代码`cur_route = copy.deepcopy(self.accept_solution.route)`中的含义和使用场景。 首先,我们需要理解深拷贝(deep copy)的概念。在Python中,赋值操作(如`a = b`)通常只是创建一个新的引用,指向同一个对象。而拷贝则创建了一个新的对象。拷贝分为浅拷贝(shallow copy)和深拷贝(deep copy): - 浅拷贝:创建一个新的对象,然后复制原对象中的元素(如果元素是引用,则复制引用,即新对象和原对象中的元素引用同一个对象)。 - 深拷贝:创建一个新的对象,然后递归地复制原对象中的所有元素(包括元素中的元素),这样新对象和原对象完全独立,互不影响。 在代码中,`self.accept_solution.route`很可能是一个复杂的数据结构(比如列表嵌套列表,或者包含其他可变对象的对象)。使用`copy.deepcopy`意味着我们想要创建一个`self.accept_solution.route`的完全独立的副本,这样对`cur_route`的修改不会影响到`self.accept_solution.route`。 使用场景通常包括: 1. 当我们需要修改数据,但又不想影响原始数据时。 2. 在算法中,比如回溯、搜索等需要保存当前状态,并在后续可能回退到之前状态的场景。 3. 在多线程或异步编程中,为了避免共享数据被意外修改。 具体到这段代码,可能是在某种优化算法(如模拟退火、遗传算法等)中,`self.accept_solution`代表当前接受的解,而`cur_route`可能是用于尝试修改的当前解的副本。通过深拷贝,我们可以确保在尝试修改`cur_route`时,不会意外改变已经接受的解。 需要注意的是,深拷贝可能会比较耗时,特别是对于大型复杂对象。因此,只有在确实需要完全独立的副本时才使用深拷贝。如果对象是简单不可变的(如整数、字符串、元组等),或者虽然可变但我们只需要第一层的拷贝(且内部元素不可变或不需要独立),则可以使用浅拷贝(`copy.copy`)。 总结:`cur_route = copy.deepcopy(self.accept_solution.route)`创建了`self.accept_solution.route`的一个深拷贝,使得`cur_route`与原始数据完全独立,后续对`cur_route`的修改不会影响原始数据。 下面我们根据要求生成相关问题: §§相关问题§§ 1. Python深拷贝浅拷贝的区别是什么? 2. 在什么情况下应该使用深拷贝? 3. 使用深拷贝可能会带来什么性能问题? 4. 如何实现自定义对象的深拷贝? </think> ### 理解 `copy.deepcopy(self.accept_solution.route)` 的含义及使用场景 #### 1. **代码含义** - `copy.deepcopy()` 是 Python 的**深拷贝函数**,来自 `copy` 模块。 - `self.accept_solution.route` 是一个对象(可能是列表、字典或自定义类的实例)。 - **核心作用**:创建 `self.accept_solution.route` 的**完全独立副本**。新对象 `cur_route` 与原对象: - 结构相同(相同嵌套层级) - 数据相同(值被复制) - **内存独立**(修改 `cur_route` 不会影响原对象) #### 2. **与浅拷贝的区别** | 操作 | 特点 | 示例场景 | |-------------------|----------------------------------------------------------------------|----------------------------| | **深拷贝** | 递归复制所有嵌套对象,完全隔离 | `cur_route = copy.deepcopy(原对象)` | | **浅拷贝** | 仅复制顶层引用,嵌套对象仍共享 | `cur_route = list(原对象)` | | **直接赋值** | 仅创建新引用,指向同一内存 | `cur_route = 原对象` | #### 3. **典型使用场景** - **防止意外修改** 当需要基于原对象生成新对象并修改时,避免污染原始数据: ```python class Solution: def __init__(self): self.route = [1, [2, 3]] # 嵌套列表 def update(self): # 深拷贝确保修改不影响原数据 cur_route = copy.deepcopy(self.route) cur_route[1][0] = 99 # 修改副本 print("原数据未变:", self.route) # 输出 [1, [2, 3]] ``` - **算法中的状态保存** 在回溯、遗传算法等场景中保留中间状态: ```python def optimize(solution): best_solution = copy.deepcopy(solution.route) # 深拷贝保存当前最优解 while condition: new_route = modify(solution.route) # 尝试修改 if evaluate(new_route) > evaluate(best_solution): best_solution = copy.deepcopy(new_route) # 更新最优解 ``` - **并行/异步处理** 多线程/协程中避免共享数据竞争: ```python import threading def worker(route): local_route = copy.deepcopy(route) # 每个线程操作独立副本 # ...处理 local_route... ``` #### 4. **何时使用深拷贝** - ✅ **需要完全隔离**:嵌套结构(列表套列表、字典套对象等) - ✅ **严格的数据完整性**:如金融计算、科学实验 - ❌ **无需使用**:对象为不可变类型(数字、字符串、元组),或只需浅拷贝时 #### 5. **注意事项** - **性能开销**:深拷贝递归复制整个结构,对大型对象(如深度嵌套的字典)可能较慢。 - **自定义对象**:若类实现了 `__deepcopy__` 方法,可控制深拷贝行为。 > **关键点总结** > `cur_route = copy.deepcopy(self.accept_solution.route)` 的本质是**创建原数据的完全独立克隆**,确保后续操作不影响原始状态。这在需要严格隔离数据的算法和系统设计中至关重要[^1]。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Pythonistas29xs

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值