图解Python中深浅拷贝
在工作中,常涉及到数据的传递,在数据传递使用过程中,可能会发生数据被修改的问题。为了防止数据被修改,就需要在传递一个副本,即使副本被修改,也不会影响原数据的使用。为了生成这个副本,就产生了拷贝。今天就说一下Python中的深浅拷贝问题。
一、深浅copy
1. 赋值运算
- l1 = [1, 2, 3, [22, 33]]
- l2 = l1
- l1.append(666)
- print(l1) # [1, 2, 3, [22, 33], 666]
- print(l2) # [1, 2, 3, [22, 33], 666]
图解:
注意:l2 = l1是一个指向,是赋值,和深浅copy无关。
2. 浅copy
其实列表是一个一个的槽位,每个槽位存储的是该对象的内存地址
- #例1. 给大列表添加元素
- l1 = [1, 2, 3, [22, 33]]
- l2 = l1.copy()
- # 或者下面这种方式,也是浅copy
- # import copy
- # l2 = copy.copy(l1)
- l1.append(666)
- print(l1) # [1, 2, 3, [22, 33], 666]
- print(l2) # [1, 2, 3, [22, 33]]
- #例2. 给小列表添加元素
- l1 = [1, 2, 3, [22, 33]]
- l2 = l1.copy()
- l1[-1].append(666)
- print(l1) # [1, 2, 3, [22, 33, 666]]
- print(l2) # [1, 2, 3, [22, 33, 666]]、
- 例3. 将l1列表中第一个元素改为6
- l1 = [1, 2, 3, [22, 33]]
- l2 = l1.copy()
- l1[0] = 6
- print(l1) # [6, 2, 3, [22, 33]]
- print(l2) # [1, 2, 3, [22, 33]]
图解:
例1
例2
例3
小结:
浅copy:会在内存中新开辟一个空间,存放这个copy的列表,但是列表里面的内容还是沿用之前对象的内存地址。
3. 深copy
- import copy
- l1 = [1, 2, 3, [22, 33]]
- l2 = copy.deepcopy(l1)
- l1.append(666)
- print(l1) # [1, 2, 3, [22, 33], 666]
- print(l2) # [1, 2, 3, [22, 33]]
图解:
本质如下图:
但是python对深copy做了一个优化,将可变的数据类型在内存中重新创建一份,而不可变的数据类型则沿用之前的,所以内存中是下面这样的:
小结:
深copy:会在内存中开辟新空间,将原列表以及列表里面的可变数据类型重新创建一份,不可变数据类型则沿用之前的。
为什么Python默认的拷贝方式是浅拷贝?
- 时间角度:浅拷贝花费时间更少。
- 空间角度:浅拷贝花费内存更少。
- 效率角度:浅拷贝只拷贝顶层数据,一般情况下比深拷贝效率高。
总结:
- 不可变对象在赋值时会开辟新空间。
- 可变对象在赋值时,修改一个的值,另一个也会发生改变。
- 深、浅拷贝对不可变对象拷贝时,不开辟新空间,相当于赋值操作。
- 浅拷贝在拷贝时,只拷贝第一层中的引用,如果元素是可变对象,并且被修改,那么拷贝的对象也会发生变化。
- 深拷贝在拷贝时,会逐层进行拷贝,直到所有的引用都是不可变对象为止。
- Python 有多种方式实现浅拷贝,copy模块的copy 函数 ,对象的 copy 函数 ,工厂方法,切片等。
- 大多数情况下,编写程序时,都是使用浅拷贝,除非有特定的需求。
- 浅拷贝的优点:拷贝速度快,占用空间少,拷贝效率高。
想要获取更多Python学习资料可以加我QQ:2955637827
图解Python中深浅拷贝的更多相关文章
- python中深浅拷贝
python的复制,深拷贝和浅拷贝的区别 在python中,对象赋值实际上是对象的引用.当创建一个对象,然后把它赋给另一个变量的时候,python并没有拷贝这个对象,而只是拷贝了这个对象的引用 一 ...
- Python中深浅拷贝 垃圾回收与 super继承(六)
1 python拷贝 深拷贝,浅拷贝 与引用三者的区别 import copy a = [1, 2, 3, 4, ['a', 'b']] #原始对象 b = a #赋值,传对象的引用 c = copy ...
- Python的深浅拷贝
Python的深浅拷贝 深浅拷贝 1. 赋值,对于list, set, dict来说, 直接赋值. 其实是把内存地址交给变量并不是复制一份内容 list1 = [']] list2 = list1 p ...
- Python原理 -- 深浅拷贝
python原理 -- 深浅拷贝 从数据类型说开去 str, num : 一次性创建, 不能被修改, 修改即是再创建. list,tuple,dict,set : 链表,当前元素记录, 下一个元素的位 ...
- Python之深浅拷贝
拷贝就是拷贝,何来深浅之说? Python中,对象的赋值,拷贝(深/浅拷贝)之间是有差异的,如果使用的时候不注意,就可能产生意外的结果 其实这个是由于共享内存导致的结果 浅拷贝 l1 = [1,2,3 ...
- 24、简述Python的深浅拷贝以及应用场景
深浅拷贝的原理 深浅拷贝用法来自copy模块. 导入模块:import copy 浅拷贝:copy.copy 深拷贝:copy.deepcopy 字面理解:浅拷贝指仅仅拷贝数据集合的第一层数据,深拷贝 ...
- Python入门-深浅拷贝
首先我们在这里先补充一下基础数据类型的一些知识: 一.循环删除 1.前面我们学了列表,字典和集合的一些操作方法:增删改查,现在我们来看一下这个问题: 有这样一个列表: lst = ['周杰伦','周润 ...
- day2学python 数据类型+深浅拷贝+循环
数据类型+深浅拷贝+循环 别的语言的数组 python不用定义 直接使用 color=['红','橙','黄','绿','青','蓝','紫'] print(color[1:3]) //打印[1,3) ...
- 简述Python的深浅拷贝以及应用场景
深浅拷贝的原理 深浅拷贝用法来自copy模块. 导入模块:import copy 浅拷贝:copy.copy 深拷贝:copy.deepcopy 字面理解:浅拷贝指仅仅拷贝数据集合的第一层数据,深拷贝 ...
随机推荐
- Java中对象在内存中的大小、分配等问题
Java创建一个对象的过程 是否对象指向的类已经加载到内存了 如果没有加载,就要经过load.linking(verification.preparation.resolution).initiali ...
- pytest失败重跑
一.说明 平常在做功能测试的时候,经常会遇到某个模块不稳定,偶然会出现一些bug,对于这种问题我们会针对此用例反复执行多次,最终复现出问题来.自动化运行用例时候,也会出现偶然的bug,可以针对单个用例 ...
- python sklearn库实现逻辑回归的实例代码
Sklearn简介 Scikit-learn(sklearn)是机器学习中常用的第三方模块,对常用的机器学习方法进行了封装,包括回归(Regression).降维(Dimensionality Red ...
- 《Spring Boot 实战纪实》之如何攥写需求文档
目录 前言 (思维篇)人人都是产品经理 1.需求文档 1.1 需求管理 1.2 如何攥写需求文档 1.3 需求关键点文档 2 原型设计 2.1 缺失的逻辑 2.2 让想法跃然纸上 3 开发设计文档 3 ...
- 「实验课选题详解」用C语言实现万年历
题目要求 编程实现万年历,要求: 可根据用户输入或系统日期进行初始化,如果用户无输入则显示系统日期所在月份的月历,并突出显示当前日期: 可根据用户输入的日期查询,并显示查询结果所在月份的月历,突出显示 ...
- Java MQTT 客户端之 Paho
Paho 自动重连后订阅的主题会清空,所以需要实现 MqttCallbackExtended 接口,在 connectComplete 方法添加订阅主题:而不是实现 MqttCallback 接口 一 ...
- PyQt(Python+Qt)学习随笔:布局控件layout的layoutSizeConstraint属性
在Qt Designer中布局控件有4个,分别是Vertical Layout(垂直布局).Horizontal Layout(水平布局).Grid Layout(网格布局).Form Layout( ...
- flask加载配置文件的三种方法
1.第一种方法也是我们最长用到的,包括我们项目中也是采用第一种的方法,加载配置文件 配置信息全部写在config.py里面,在主app.py的文件中写入 import config app.confi ...
- 关于Lombok框架子类继承时EqualsAndHashCode注解的callSuper取值的思考
先看例子(原始用例来源于这篇文章): TV类 @Getter @Setter //@EqualsAndHashCode @AllArgsConstructor @NoArgsConstructor p ...
- 谈Vite在Electron环境下吃花卷拉馒头的现象
缘起 在Electron的渲染进程中(也就是页面代码中), 我们常常使用process.env来携带一些环境变量, 比如HTTP服务地址的基质,本地静态资源的路径等 这样做主要有两个目的 一个是方便开 ...