深入理解Python深拷贝(deepcopy)、浅拷贝(copy)、等号拷贝----看了还不懂找我

article/2025/1/18 17:56:58

         编程中难免会遇到copy(浅拷贝)与deepcopy(深拷贝)问题,一不小心就会掉进坑中了,或许很多人只知道有深浅拷贝,但是你又知道copy和"="拷贝有什么区别么?也许很少有人对二者的区别能讲出一二三吧!下面这篇文章就对深拷贝(deepcopy)、浅拷贝(copy)、等号拷贝进行深入的讲解。

        本文不是在网上抄袭别人的,而是本人通过研究学习后的自我总结,我想当你看完这篇文章后,1. 你会知道python的变量存储机制;2. 你会深浅拷贝以及等号拷贝的差异所在了;3. 你会理解为什么有的值改变,有的拷贝跟着变化,有的不会变化的根本原因所在了。当然如果本文有不正确的地方,欢迎大家批判指正。

首先在python中,什么是浅拷贝,什么是深拷贝呢?什么是等号拷贝(形如:bb = aa)呢?有谁能一句话解释清楚,他们的区别又在哪里?-----一定记住针只有对复杂对象才有区别意义!!!因为对于简单对象,他们是没有区别的!

主要是针对复杂结构对象,复杂结构对象就是嵌套两层及以上的子对象,比如:即列表中嵌套子列表,像[1, [2, 3]]这种结构

复杂对象中的深浅拷贝:

一句话解释(=)等号拷贝:当于对于电脑中某个文件夹新建了一个快捷图标,快捷图标永远和原文件是一致的。

一句话解释(copy)浅拷贝:相当于对于电脑中某个文件夹内部的所有子文件夹新建了快捷图标,放到新的文件夹中,所以内部子文件夹内数据会跟着原来文件的改变而改变。

一句话解释(deepcopy)深拷贝:相当于对于电脑中某个文件夹用u盘拷贝了一个备份。所以原来电脑中文件夹内文件改变时,u盘的文件是不会变化的。

官方解释:

  • 浅层拷贝 构造一个新的复合对象,然后(在尽可能的范围内)将原始对象中找到的对象的 引用 插入其中。

  • 深层拷贝构造一个新的复合对象,然后,递归地将在原始对象里找到的对象的 副本 插入其中

要弄清楚拷贝原理,首先应该弄清楚Python变量存储机制

Python中变量的存储机制

1. aa = 1的存储机制

当aa = 1 时,首先Python会在内存中新开辟一个空间存储数字“1”,然后将该内容的地址赋值给变量‘aa’。有点像如下图所示

2. bb = aa的复制机制

对于正常的“=” 赋值, 比如 bb = aa,则有

3. 形如or_list = [1, [2, 3]]的复制对象,他们的存储机制是如何的呢?

读者可以先自我思考一下,在本文的后面讲解中,会给出解释。

Python中复杂对象,等号拷贝,copy浅拷贝,deepcopy深拷贝机制

1. 三者拷贝后的ID差异

看以下代码初始列表为 or_list = [1, [2, 3]],分别进行"="拷贝,copy浅拷贝,deepcopy深拷贝

操作如下   

    eq_list = or_listsh_list = copy(or_list)de_list = deepcopy(or_list),

通过id可以看出三者和原来list的内存地址信息,如下:

    id(or_list)= 2269079198528id(eq_list)= 2269079198528id(sh_list)= 2269076677056id(de_list)= 2269076677632

【解释说明】:

1. 对于等号拷贝,没有新建新的内存空间,只是吧eq_list变量指向or_list变量相同的地址,通过id可以看出来,两个地址一样 id(or_list)= 2269079198528 和 id(eq_list)= 2269079198528

2. 对于copy拷贝,新创建了内存空间,并且把sh_list变量指向了该新地址。此时的新地址为id(sh_list)= 2269076677056

3. 对于deepcopy拷贝,也新创建了一个内存空间,并且整个List也指向了新的地址。此时的新地址为 id(de_list)= 2269076677632

2. 查看List的不同位置的id值

再通过id查看List内部位置存储的是什么,可以看到不同操作,不同位置就有差异了。

1. or_list[0]位置,所有的拷贝后的ID都是相同的,为什么呢?

2. or_list[1]位置,只有deepcopy拷贝不同,其它拷贝的id不变,这是为什么呢?

3. or_list[1][0]和or_list[1][1]的id为什么所有拷贝又都是一样的呢?

5.  ======列表第一个位置的ID值=======  id(or_list[0]) = 2269075013872id(eq_list[0]) = 2269075013872id(sh_list[0]) = 2269075013872id(de_list[0]) = 22690750138726.  ======列表第二个位置的ID值===========id(or_list[1]) = 2269076677312id(eq_list[1]) = 2269076677312id(sh_list[1]) = 2269076677312id(de_list[1]) = 22690770812166.1 ====列表第二个位置的子列表第一位置的ID值=====id(or_list[1][0]) = 2269075013904id(eq_list[1][0]) = 2269075013904id(sh_list[1][0]) = 2269075013904id(de_list[1][0]) = 22690750139046.2 ====列表第二个位置的子列表第二位置的ID值=====id(or_list[1][1]) = 2269075013936id(eq_list[1][1]) = 2269075013936id(sh_list[1][1]) = 2269075013936id(de_list[1][1]) = 2269075013936

【解释说明】

要解释清楚上面的为什么,就需要弄明白python中形如or_list = [1, [2, 3]]这样的存储原理。

首先,看形如or_list = [1, [2, 3]]的存储原理,在python中,形如or_list = [1, [2, 3]]的复制对象的存储原理为如下图所示:

其次,看不同拷贝的原理。

1. 对于等号拷贝,拷贝后实际上是将List的地址引用直接给了等号拷贝的变量,示意图如下所示

2. 对于copy拷贝,拷贝后的实际上新建了一个内存空间,一个用于存储List本身,内部子对象引用原来的地址,示意图如下:

3. 对于deepcopy拷贝,拷贝后的实际上新建了两个内存空间,一个用于存储List,另一个存储List的子对象,如果有更多,那么就会创建更多的内存空间。示意图如下:

最后,来回答上面的问题

1. or_list[0]位置,所有的拷贝后的ID都是相同的,为什么呢?

回答1:因为对于数字1,它是简单对象,不是复杂对象,不管怎么拷贝,他们都是相同的。

2. or_list[1]位置,只有deepcopy拷贝不同,其它拷贝的id不变,这是为什么呢?

回答2:对于List[1]位置,它是一个复杂对象,所以只有deepcopy新建了新的内存,所以只有它的id变化了。

3. or_list[1][0]和or_list[1][1]的id为什么所有拷贝又都是一样的呢?

回答3:因为这两个位置都是存储的是简单对象,所以在所有的拷贝之后,id是不会变的。

Python中复杂对象修改值后,等号拷贝,copy浅拷贝,deepcopy深拷贝变化情况详解

将所有的拷贝原理图放到一起,可以看到他们的区别和联系,如下图所示。以下是各个位置在发生改变后不同拷贝的变化机制详解。

1. 改变or_list[1][0]的值时

进行or_list[1][0] = 4操作,结果如下所示:

可以看出原始该位置存储的id是*176,初始列表该位置发生改变时,等号拷贝和copy浅拷贝也跟着发生了改变,但是deepcopy深拷贝没有发生变化。为什么会这样呢?改变的原理可以看下面的示意图。因为deepcopy是在List[1]位置就创建了新的内存空间,其它拷贝并没有,他们还是引用的原始列表相同的内存空间,所以才会跟着一起变化

======更改前:or列表的子列表第二个位置的id值===========
id(or_list[1][0])= 2269075013904
id(eq_list[1][0])= 2269075013904
id(sh_list[1][0])= 2269075013904
id(de_list[1][0])= 2269075013904进行更改: or_list[1][0] = 4 
======更改后:or列表的子列表第二个位置的ID值===========
id(or_list[1][0])= 2269075013968
id(eq_list[1][0])= 2269075013968
id(sh_list[1][0])= 2269075013968
id(de_list[1][0])= 2269075013904
======更改后变量值===========
or_list_after_change =  [1, [4, 3]]
eq_list_after_change =  [1, [4, 3]]
sh_list_after_change =  [1, [4, 3]]
de_list_after_change =  [1, [2, 3]]

 2. 改变List[0]位置的值时

改变第一层的元素时,只有等号拷贝跟着改变了,是因为copy浅拷贝和deepcopy深拷贝都是新开辟了内存空间,存储List[0],List[1],所以当原始的List[0]发生改变时,这两个拷贝没有任何影响,具体原理查看以下示意图

======更改前:or列表的第一个位置的ID值===========
id(or_list[0])= 2269075013872
id(eq_list[0])= 2269075013872
id(sh_list[0])= 2269075013872
id(de_list[0])= 2269075013872进行更改: or_list[0] = 5 
======更改后:or列表的第一个位置的ID值===========
id(or_list[0])= 2269075014000
id(eq_list[0])= 2269075014000
id(sh_list[0])= 2269075013872
id(de_list[0])= 2269075013872======更改后变量值===========
or_list_after_change =  [5, [4, 3]]
eq_list_after_change =  [5, [4, 3]]
sh_list_after_change =  [1, [4, 3]]
de_list_after_change =  [1, [2, 3]]

 3. 改变List[1]位置的值时

原理同3改变List[0]位置的值。原理和代码参考以下代码是示意图

======更改前: or列表的第一个位置的ID值===========
id(or_list[1])= 2269076677312
id(eq_list[1])= 2269076677312
id(sh_list[1])= 2269076677312
id(de_list[1])= 2269077081216进行更改: or_list[1] = {'1': 'a', 'b': 1}
======更改后: or列表的第一个位置的ID值===========
id(or_list[1])= 2269076306688
id(eq_list[1])= 2269076306688
id(sh_list[1])= 2269076677312
id(de_list[1])= 2269077081216======更改后变量值===========
or_list_after_change =  [5, {'1': 'a', 'b': 10}]
eq_list_after_change =  [5, {'1': 'a', 'b': 10}]
sh_list_after_change =  [1, [4, 3]]
de_list_after_change =  [1, [2, 3]]


http://chatgpt.dhexx.cn/article/IUoxAJy6.shtml

相关文章

Python-copy()与deepcopy()区别

最近在实习,boss给布置了一个python的小任务,学习过程中发现copy()和deepcopy()这对好基友实在是有点过分,搞的博主就有点傻傻分不清啊,但是呢本着一探到底的精神,还是要…

三分钟入门大数据之什么是用户画像?

哈喽,大家好,我是汉斯老师。近几年来,互联网行业由于较高的薪资收入,受到许多人的追捧。很多年轻的学子,或是其他行业的有志青年,都想要投身到这个行业中来。然而一方面受到“互联网寒冬”的影响&#xff0…

什么是用户画像?金融行业大数据用户画像实践

金融消费者逐渐年轻化,80、90后成为客户主力,他们的消费意识和金融意识正在增强。金融服务正在从以产品为中心,转向以消费者为中心。所有金融行业面对的最大挑战是消费者的消费行为和消费需求的转变,金融企业迫切需要为产品寻找目…

银行用户画像简介

当我们讨论产品、需求、场景、用户体验时,往往需要将焦点聚集在某类人群上,用户画像便是一种抽象的方法,是目标用户的集合。本文作者对银行用户画像体系的建设进行了分析,希望能给你带来一些帮助。 用户画像的正式英文名称是User …

用户画像基础之用户画像是什么

目录 0. 相关文章链接 1. 用户画像是什么 2. 画像简介 3. 标签类型 注:此博文为根据 赵宏田 老师的 用户画像方法论与工程化解决方案 一书读后笔记而来,仅供学习使用 0. 相关文章链接 用户画像文章汇总 1. 用户画像是什么 在互联网步入大数据时代…

详解用户画像

01画像简介 用户画像,即用户信息标签化,通过收集用户的社会属性、消费习惯、偏好特征等各个维度的数据,进而对用户或者产品特征属性进行刻画,并对这些特征进行分析、统计,挖掘潜在价值信息,从而抽象出用户的…

用户画像——什么是用户画像?和用户画像的计算框架选型

用户画像——什么是用户画像?和用户画像的计算框架选型 1.什么是用户画像? 1.1 应用场景 1.1.1 精细化运营 1.1.2 推荐系统 1.2 概念定义 1.2.1 总结场景对数据的需求 1.2.2 实现这些场的数据结构 1.2.3 用户画像的概念 2.用户画像…

什么是用户画像,流程、方法是什么?

什么是用户画像,流程、方法是什么? 01 用户画像概述1. 什么是用户画像2. 为什么需要用户画像 02 用户画像流程1. 整体流程1)目标分析2)标签体系构建3)画像构建 2. 标签体系1)事实标签2)模型标签3&#xff…

一文让你彻底明白,到底什么是用户画像?

写在前面: 博主是一名大数据的初学者,昵称来源于《爱丽丝梦游仙境》中的Alice和自己的昵称。作为一名互联网小白,写博客一方面是为了记录自己的学习历程,一方面是希望能够帮助到很多和自己一样处于起步阶段的萌新。由于水平有限&a…

什么是用户画像——从零开始搭建实时用户画像(一)

用户画像 简介 用户画像,作为一种勾画目标用户、联系用户诉求与设计方向的有效工具,用户画像在各领域得到了广泛的应用。 用户画像最初是在电商领域得到应用的,在大数据时代背景下,用户信息充斥在网络中,将用户的每…

帮你更好地了解什么是用户画像

用户画像是一个挺新颖的词,最初它是大数据行业言必及之的时髦概念。现在我们运营谈及用户画像,它也是和精准营销、精细化运营直接钩挂的。 什么是用户画像? 在中文的语言环境中,用户画像是用来描述用户特征(用户背景、特征、性格标签、行为场景等)和联系用户需求与产品…

什么是用户画像,用户画像的作用是什么?

更多行业干货,上网易游戏学院app查看! https://game.academy.163.com/ssi/app/?referrer=niuke 什么是用户画像? 用户画像,由交互大师艾伦库伯在他的著作《交互设计精髓4》(《AboutFace 4》)中提出。他在书中介绍:“用户画像来源于研究中真实用户的行为和动机。用户画…

什么是用户画像?如何构建用户画像?

我们通过这篇文章,介绍我们理解的两种用户画像(User Persona 和 User Profile),以及如何构建用户画像(User Profile)的标签体系并驱动产品智能。 User Persona 第一种用户画像(User Persona&a…

用户画像(一)

本文转自:用户画像实践篇 终于有人把用户画像的流程、方法讲明白了 1 什么是用户画像 1. 1 概述 通过分析用户的基础信息、特征偏好、社会属性等各维度的数据,刻画出用户的信息全貌, 从中挖掘用户价值,从而提供个性化推荐、精准…

什么是真正的用户画像

如今在这个大数据时代,每个用户都被标签化,运用用户画像的方式了解用户,从而推送相关消息;最常见的情况就是你买了商品后,推荐会自动推送与此商品相关的商品,促进消费;本文作者分享了关于什么是…

用户画像:概述【从应用角度来看,可以分为行为画像、健康画像、企业信用画像、个人信用画像、静态产品画像、旋转设备画像、社会画像、经济画像...】

一、 什么是用户画像 用户画像是指根据用户的属性、用户偏好、生活习惯、用户行为等信息而抽象出来的标签化用户模型。通俗说就是给用户打标签,而标签是通过对用户信息分析而来的高度精炼的特征标识。通过打标签可以利用一些高度概括、容易理解的特征来描述用户&…

对话机器人---智能客服

https://blog.csdn.net/qq_40027052/article/details/78723576 详细的介绍了对话机器人涉及到的所有知识和技术。 整个对话机器人涉及到的知识点,本人属于自然语言处理的研究方向,所以还要很多需要学习的地方。 在实现一个对话机器人的过程中&#xff0c…

安排,Mysql入门到精通教程

来源: 来自网络,如侵权请告知博主删除????。 仅学习使用,请勿用于其他~ spring,vue的,前后端的都给童鞋安排过一些了,有童鞋让我安排Mysql了,走起 目录: 课时1:Mysql介绍.mp4课…

js 面向对象的三大特性

一。封装 所谓封装的概念,是不希望暴露函数中属性或者方法的地址,使外界不能操作,但是可以暴露特有的公有接口,可以利用接口操作。 function hello(){var namexiaoming;this.getnamefunction(){return name;}} 封装在平日里用的比…