Python深拷贝与浅拷贝的区别

Python深拷贝与浅拷贝的区别首先深拷贝和浅拷贝都是对象的拷贝 都会生成一个看起来相同的对象 他们本质的区别是拷贝出来的对象的地址是否和原对象一样 也就是地址的复制还是值的复制的区别 什么是可变对象 什么是不可变对象 可变对象是指 一个对象在不改变其所指向的地址的前提下 可以修改其所指向的地址中的值 不可变对象是指 一个对象所指向的地址上值是不能修改的 如果你修改了这个对象的值 那么它指向的地址就改变了 相当

首先深拷贝和浅拷贝都是对象的拷贝,都会生成一个看起来相同的对象,他们本质的区别是拷贝出来的对象的地址是否和原对象一样,也就是地址的复制还是值的复制的区别。

 

什么是可变对象,什么是不可变对象:

可变对象是指,一个对象在不改变其所指向的地址的前提下,可以修改其所指向的地址中的值;

不可变对象是指,一个对象所指向的地址上值是不能修改的,如果你修改了这个对象的值,那么它指向的地址就改变了,相当于你把这个对象指向的值复制出来一份,然后做了修改后存到另一个地址上了,但是可变对象就不会做这样的动作,而是直接在对象所指的地址上把值给改变了,而这个对象依然指向这个地址。

 

深拷贝和浅拷贝需要注意的地方就是可变元素的拷贝:

在浅拷贝时,拷贝出来的新对象的地址和原对象是不一样的,但是新对象里面的可变元素(如列表)的地址和原对象里的可变元素的地址是相同的,也就是说浅拷贝它拷贝的是浅层次的数据结构(不可变元素),对象里的可变元素作为深层次的数据结构并没有被拷贝到新地址里面去,而是和原对象里的可变元素指向同一个地址,所以在新对象或原对象里对这个可变元素做修改时,两个对象是同时改变的,但是深拷贝不会这样,这个是浅拷贝相对于深拷贝最根本的区别。

 

举例说明:

Python深拷贝与浅拷贝的区别

从程序的结果来看,列表a和b是赋值操作,两个对象完全指向同一个地址,a和b就是同一块地址的两个引用,其实就是一个东西,所以一个对象在修改浅层元素(不可变)或深层元素(可变)时,另一个对象也同时在变;

c是a进行浅拷贝生成的对象,可以看到a(或b)和c两个对象整体的id是不同的,但是里面的第5个元素-列表的地址却是相同的(指向同一个地址),所以b在浅层次元素层面(不可变)增加一个元素时,c并没跟着增加,但是b的第5个元素-列表在增加一个元素时,c的第5个元素也跟着增加了,这就是因为b和c的第5个元素-列表是指向同一个地址的,这个地址上的值变了,在两个地方会同时改变;

再看d,d的浅层次元素(不可变)和 深层次元素(可变)的地址和a,b,c都不一样,所以,a,b,c无论怎么修改,d都不会跟着改变,这就是深拷贝的结果。

 

也可以这样理解:

深拷贝就是完全跟以前就没有任何关系了,原来的对象怎么改都不会影响当前对象

浅拷贝,原对象的list元素改变的话会改变当前对象,如果当前对象中list元素改变了,也同样会影响原对象。

浅拷贝就是藕断丝连

深拷贝就是离婚了

 

通常复制的时候要用深拷贝,因为浅拷贝后,两个对象中不可变对象指向不同地址,相互不会改变,但是两个对象中的可变元素是指向相同的地址,一个变了,另一个会同时改变,会有影响(list是可变对象)。

 

如果要让原list和copy list没有影响怎么办?

用深拷贝,拷贝后完全开辟新的内存地址来保存之前的对象,虽然可能地址执行的内容可能相同(同一个地址,例如’s’),但是不会相互影响。

比如:

List1=[‘a’,’b’,’c’]

List2=[‘a’,’b’,’c’]

两个列表中的’a’的地址是相同的

Id(list1[0])=id(list2[0]),但是两个列表的地址是不同的

 

通常来讲不可变元素包含:

int,float,complex,long,str,unicode,tuple

参考: https://www.cnblogs.com/xiaxiaoxu/p/9742452.html

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/211412.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月18日 下午10:29
下一篇 2026年3月18日 下午10:30


相关推荐

  • 备忘录模式实例_iphone语音备忘录无法分享

    备忘录模式实例_iphone语音备忘录无法分享备忘录模式 Motivation动机模式定义实例结构要点总结笔记动机在软件构建过程中,某些对象的状态在转换过程中,可能由于某种需要,要求程序能够回溯对象之前处于某个点时的状态.如果使用一些共有接口来让其他对象得到对象的状态,便会暴露对象的实现细节.如何实现对象状态的良好保存与回复?但同时又不会因此而破坏对象的封装性模式定义在不破坏封装性的前提下.捕获一个对象的内部状态,并在该对象之外保存这个状态.这样以后就可以将该对象恢复到原先保存的状态实例朴素class Memento{ stri

    2022年8月11日
    7
  • 数据库实例名

    数据库实例名一 数据库实例名什么是数据库实例名 数据库实例名是用于和操作系统进行联系的标识 就是说数据库和操作系统之间的交互用的是数据库实例名 实例名也被写入参数文件中 该参数为 instance name 在 winnt 平台中 实例名同时也被写入注册表 数据库名和实例名可以相同也可以不同 在一般情况下 数据库名和实例名是一对一的关系 但如果在 oracle 并行服务器架构 即 oracle 实时应用集群 中 数据库名和实例名是一对多的关系 查询当前数据库实例名方法一 selectinstan namefrom

    2026年3月26日
    1
  • 图文教程本地部署开源扣子Coze Studio工作流并接入 Gemini 大模型(windows亲测) Coze Studio 本地部署、Gemini 模型接入、开源 AI 工具平台、大模型工作流搭建

    图文教程本地部署开源扣子Coze Studio工作流并接入 Gemini 大模型(windows亲测) Coze Studio 本地部署、Gemini 模型接入、开源 AI 工具平台、大模型工作流搭建

    2026年3月12日
    1
  • Qcom 平台 LK 阶段配置 I2C[通俗易懂]

    Qcom 平台 LK 阶段配置 I2C[通俗易懂]本文着重介绍,如何在qcom平台的LK阶段配置和使用I2C。硬件平台:msm8909软件平台:Android5.0、Android8.0I2C设备:ADV7533

    2022年10月19日
    4
  • jmeter正则提取器用法_jmeter字符串截取

    jmeter正则提取器用法_jmeter字符串截取JMeter正则表达式提取器 转自:http://desert3.iteye.com/blog/1394934//提取HTML中隐藏域的值^(.*)$ //提取整个response返回提取MyLabel关联的input的值MyLabel”(.+:create:.+?)”  //提取下面link的href的值JSESSIONI

    2025年10月21日
    4
  • 2021.7goland激活码【2021.7最新】

    (2021.7goland激活码)2021最新分享一个能用的的激活码出来,希望能帮到需要激活的朋友。目前这个是能用的,但是用的人多了之后也会失效,会不定时更新的,大家持续关注此网站~IntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,下面是详细链接哦~https://javaforall.net/100143.html…

    2022年3月21日
    41

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号