深拷贝和浅拷贝的区别 | 学习笔记

简介: 快速学习 深拷贝和浅拷贝的区别

开发者学堂课程【Python入门 2020年版深拷贝和浅拷贝的区别】学习笔记,与课程紧密联系,让用户快速学习知识。

课程地址:https://developer.aliyun.com/learning/course/639/detail/10307


深拷贝和浅拷贝的区别


内容介绍

一、浅拷贝回顾

二、深拷贝

三、网址推荐


一、浅拷贝回顾

首先我们定义一个 numsnums1 = nums 为等于时,表示相互关联的操作既不是深复制也不是浅复制,它仅仅是一个指向,是赋值操作。

1.赋值

#浅复制(拷贝)

nums = [12345]

nums1 = nums     #深拷贝/浅拷贝?都不是,只是一个赋值

2.  浅复制回顾

1)使用 Copy 方法

nums2 = nums.copy()表示浅复制,两者内容一致,但并不是同一个对象,无论修改其中的任何一个,都不会改变另一个的内容。

代码

nums = [12345]

nums2 = nums.copy()#浅复制。两个内容一模一样,但是不是同一个对象

2)使用 copy 模块

除此之外还可以使用 copy 模块,nums3 = copy.copy(nums)

来进行浅拷贝,和 nums2 = nums.copy() 两者的效果一致。

代码

import copy

nums = [12345]

#浅拷贝,两个内容一模一样,但是不是同一个对象

nums2 = nums.copy()

nums3 = copy.copy(nums)


二、深拷贝

深拷贝与浅拷贝不一样,只能使用 copy 模块实现,同时涉及到列表的嵌套。定义一个 words 列表并在其中添加嵌套。

1.引例

代码

import copy

#深拷贝,只能使用 copy 横块实现

words =[' hello', 'good '[100200300]'yes', 'hi', 'ok' ]

#words1words 的浅拷贝

#浅拷贝认为只拷贝了一层

words1 = words.copy() //words 浅复制一份给 words1

words[0] = ‘你好   //word 中第一个元素变为‘你好’

print(words1) //输出 words1

words[2][0] = 1  //改变嵌套列表中的元素

print(words1)  //再次输出 words1

输出结果

[ ' hello', 'good '[100200300]'yes', 'hi', 'ok' ]

[ ' hello', 'good ',[1200300]'yes', 'hi', 'ok' ]

思路解析:

Words 如今指向一块内存空间,此时又有一个 words1又复制了 words 指向内存空间中的所有元素,同时指向另一个空间。两者是不同的内存地址。此时将 words[0]改为你好word1[0]中的内容不会发生改变。

1.png

但如果改变 word 中嵌套的列表中的第一个元素 words[2][2]1,再次输出浅拷贝生成的 words1,会发现 word1中的对应的元素发生了改变。

因为浅拷贝被认为只拷贝了一层,所以 words 嵌套的内层列表并没有被拷贝,即列表中嵌套的如果是列表元素,不会再被拷贝。而是两者都指向该列表。

将内层列表的第一个元素100改为1时,words1是与 Word 共同指向嵌套部分的列表,所以输出的结果也变为1

1.png

2.深拷贝

深拷贝只可以用 copy 模块来实现,如要对 words 进行深拷贝写法为 words2 = copy.deepcopy(words)

代码

import copy

#深拷贝,只能使用 copy 横块实现

words = [ ' hello', 'good '[100200300]'yes', 'hi', 'ok' ]

#深拷贝的 words2

words2 = copy.deepcopy(words)

words[0] = ‘你好

print(words2)

words[2][0] = 1

print(words2)

输出结果

[ ' hello', 'good '[100200300]'yes', 'hi', 'ok' ]

[ ' hello', 'good '[100200300]'yes', 'hi', 'ok' ]

words2和 word1不同,它是将 word 里全都拷贝过来。不管 word 里有任何嵌套列表都完全复制下来。

如将 words[0]改为你好或者是将 word 里嵌套的列表第一个元素进行修改,再输出 word2的结果都可以看出不会有任何的变化。实现了真正的两个独立的空间。

Tip:在元素遍历拿出来依次拷贝也不一定是深拷贝,需要通过遍历深度来判断。

1.png


三、网站推荐

同时我们可以登录 pythontutor.com 网站在其中的 Python Tutor 中去查看我们的代码的虚拟运行过程依次判断理解深拷贝。

首先在网站中输入代码,点击虚拟化执行代码。

网址:pythontutor.com

代码

import copy

words = [ ' hello', 'good '[100200300]'yes', 'hi', 'ok' ]

Word1 = words.copy()

words2 = copy.deepcopy(words)

words[2][0] = 1

1.png

1.png

虚拟执行过程:

可以看出,words 在指向其中嵌套的列表时,指向的是另一块内存。当执行第三行代码浅复制时,words1里的嵌套列表和 word 指向的是同一块内存,所以当改变嵌套列表元素时,会对应发生改变。

1.png

而当执行第四行的深复制代码时,word2中的嵌套列表并没有和 word 指向同一内存地址,而是完整的复制下 word 的内容,再全部指向另一块内存地址。

1.png

最后将 words[2][0]Word 中嵌套列表的第一个元素变为1,可以看到 words 和浅复制结果 word1指向的数据发生变化,而 words2并没发生变化。

1.png

相关文章
|
Kubernetes 关系型数据库 MySQL
ChaosBlade常见问题之数据库进行故障注入报错ibdata1文件异常如何解决
ChaosBlade 是一个开源的混沌工程实验工具,旨在通过模拟各种常见的硬件、软件、网络、应用等故障,帮助开发者在测试环境中验证系统的容错和自动恢复能力。以下是关于ChaosBlade的一些常见问题合集:
480 1
|
SQL 自然语言处理 Java
Springboot项目中使用Elasticsearch的RestClient
上一篇介绍了Elasticsearch的入门《5000字详说Elasticsearch入门(一)》,本篇介绍Springboot如何集成使用Elasticsearch。分为3步:配置properties文件、引入pom依赖、配置RestHighLevelClient类。
28641 1
|
缓存 前端开发 JavaScript
|
10月前
YOLOv11改进策略【损失函数篇】| 通过辅助边界框计算IoU提升检测效果(Inner_GIoU、Inner_DIoU、Inner_CIoU、Inner_EIoU、Inner_SIoU)
YOLOv11改进策略【损失函数篇】| 通过辅助边界框计算IoU提升检测效果(Inner_GIoU、Inner_DIoU、Inner_CIoU、Inner_EIoU、Inner_SIoU)
1080 4
YOLOv11改进策略【损失函数篇】| 通过辅助边界框计算IoU提升检测效果(Inner_GIoU、Inner_DIoU、Inner_CIoU、Inner_EIoU、Inner_SIoU)
|
10月前
|
运维 测试技术 API
(2)深度对比:Apipost vs Apifox (2)文档功能
本文深入对比Apipost和Apifox的API文档管理功能。两者都能生成精美且详细的API文档,涵盖响应体、请求示例等关键信息。Apipost界面设计高效简洁,文档查看与编辑无需频繁切换页面,整体体验流畅;而Apifox功能全面但稍显复杂。选择工具应根据个人习惯和团队需求决定。后续还将对比两者的更多功能,如Mock数据、性能测试及团队协作等。
|
uml
UML 类图几种关系(依赖、关联、泛化、实现、聚合、组合)及其对应代码
UML 类图几种关系(依赖、关联、泛化、实现、聚合、组合)及其对应代码
3596 0
|
SQL 安全 测试技术
Burpsuite Scanner主动扫描生成安全评估报告
Burpsuite Scanner主动扫描生成安全评估报告
|
分布式计算 DataWorks 搜索推荐
聊聊DataWorks这个大数据开发治理平台
聊聊DataWorks这个大数据开发治理平台
336 2
|
安全 开发者 Python
Python的内存管理pymalloc
Python的内存管理pymalloc
147 1
|
机器学习/深度学习 数据采集 算法
Python机器学习:Scikit-learn库的高效使用技巧
【10月更文挑战第28天】Scikit-learn 是 Python 中最受欢迎的机器学习库之一,以其简洁的 API、丰富的算法和良好的文档支持而受到开发者喜爱。本文介绍了 Scikit-learn 的高效使用技巧,包括数据预处理(如使用 Pipeline 和 ColumnTransformer)、模型选择与评估(如交叉验证和 GridSearchCV)以及模型持久化(如使用 joblib)。通过这些技巧,你可以在机器学习项目中事半功倍。
307 3