当前位置: 首页 > news >正文

Python中浅拷贝和深拷贝的理解

浅拷贝(Shallow Copy)‌

定义

创建一个新对象,但仅复制原对象的‌顶层元素引用‌(不递归复制嵌套的可变子对象)。

特点

顶层独立‌:新对象和原对象的容器本身是独立的,修改顶层元素(如替换列表中的某个元素)不会相互影响。
子对象共享‌:嵌套的可变子对象(如列表中的子列表、字典中的子字典)仍被共享,修改子对象内容会影响所有引用它的对象。

详解

如果不理解以上顶层元素和嵌套可变子对象的含义,可以看看下面的解释:

在浅拷贝中,对于原始列表中的每一个元素,浅拷贝会创建一个新的列表,然后将原始列表中每个元素的引用复制到新列表中。
但是,这里要注意元素的性质:

  • 如果元素是不可变对象(如整数、字符串、元组等),那么即使共享引用也没有关系,因为不可变对象不能修改,所以修改操作会创建新对象,不会影响其他引用。
  • 如果元素是可变对象(如列表、字典等),那么浅拷贝后,新列表和原列表中对应位置仍然引用同一个可变对象。因此,通过一个列表修改这个可变对象,另一个列表也会看到变化。

所以,浅拷贝后的两个对象(原列表和新列表)本身是两个不同的对象(即它们的id不同),但是它们内部的元素(特别是可变元素是共享的(即相同的引用)。

举个例子:

original_list = [1, 2, [3, 4]]
copied_list = copy.copy(original_list)

这时:

  • original_list 和 copied_list 是两个不同的列表对象(id不同)。
  • 对于前两个不可变元素(整数1和2),在两个列表中是独立的吗?实际上,它们共享相同的引用,但因为整数是不可变的,所以修改其中一个列表的顶层元素(比如将第一个元素改为5)不会影响另一个。
  • 但是,对于第三个元素,它是一个列表(可变对象),所以两个列表的第三个元素都指向同一个列表对象。因此,如果通过其中一个列表修改这个嵌套列表(例如:original_list[2][0] = 100),那么另一个列表也会看到这个改变。

注意:修改顶层元素和修改嵌套元素的不同:

  • 如果执行 copied_list[0] = 10,这只会改变copied_list的第一个元素,而original_list的第一个元素还是1。这是因为列表的顶层元素是独立的(每个位置存储的是引用,但是赋值操作只是改变copied_list的第一个引用,不会影响original_list)。
  • 但是,如果执行 copied_list[2][0] = 100,那么由于copied_list[2]和original_list[2]引用的是同一个列表,所以这个修改会同时反映在两个列表中。


因此,我们可以这样总结浅拷贝

  • 创建一个新列表(新对象)。
  • 将原列表中的每一个元素的引用(内存地址)复制到新列表中。
  • 因此,新列表和原列表在内存中是两个独立的列表,但是它们内部的元素(尤其是可变元素)是共享的。

所以,对于顶层元素(即直接包含在列表中的元素):

  • 如果它们是可变对象,那么修改这些可变对象的内容(而不是替换整个对象)会影响到另一个列表。
  • 如果替换顶层元素(比如给某个索引重新赋值一个新对象),那么只是改变了一个列表的该索引处的引用,另一个列表不变。

适用场景

  • 对象结构简单(无嵌套可变对象)
  • 需要高效复制且允许共享子对象时

这样一解释深拷贝就显得容易理解多了吧↓

深拷贝 (Deep Copy)

定义

创建一个新对象,并‌递归复制‌原对象及其所有嵌套子对象,完全独立于原对象。

特点

  • 完全独立‌:新对象与原对象及其所有子对象均无引用共享,任何修改互不影响。
  • 性能开销‌:因需递归复制所有层级,比浅拷贝更耗时耗内存。

实现方式

import copy
new_list = copy.deepcopy(original_list)  # 深拷贝

适用场景

  • 对象结构复杂(含多层嵌套可变对象)
  • 需要完全独立的副本时

http://www.dtcms.com/a/295863.html

相关文章:

  • 力扣 hot100 Day54
  • mvn dependency:tree 使用详解?
  • Leetcode 07 java
  • 赋能决策与创新的数据引擎:数据分析平台的价值与未来
  • b-up:Enzo_mi:Transformer DETR系列
  • 10_Spring Boot 中的 @Scheduled 注解是单线程还是多线程?同步还是异步?
  • 基于深度学习的肺癌肿瘤细胞图像识别与分类系统
  • 技术赋能多元探索:我的技术成长与行业洞察
  • 解决 WSL 中无法访问 registry-1.docker.io/v2/,无法用 docker 拉取 image
  • 新能源电池厂自动化应用:Modbus TCP转DeviceNet实践
  • IDM下载失败全面排查指南
  • 医疗设备自动化升级:Modbus TCP与DeviceNet的协议协同实践
  • DPO:大语言模型偏好学习的高效方案
  • Python 程序设计讲义(15):Python 的数据运算——位运算
  • Opentrons 模块化平台与AI技术助力智能移液创新,赋能AAW™自动化工作站
  • 深入探索Amazon SQS:构建弹性微服务与无服务器应用的秘密武器
  • 如何在Ubuntu系统下创建桌面快捷方式
  • Vue 3 项目性能优化指南
  • rk3588开发板使用硬件编码处理视频
  • 如何在 Windows 上安装 MongoDB 及常见问题
  • AI总结视频以及谷歌浏览器插件安装步骤
  • RAGFlow:检索增强生成技术的高效实现与深度探索
  • Day02_C++编程
  • 基于U-Net的结冰检测系统实现
  • C11补充
  • SGLang + 分布式推理部署DeepSeek671B满血版
  • 数据结构-5(二叉树)
  • pytorch-geometric包(torch_scatter、torch_sparse、torch_cluster)
  • 服务器带宽具体是指什么意思?
  • PyTorch中神经网络的模型构建