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

引用,浅拷贝,深拷贝

引用

无论是可变数据类型还是不可变的(指内部元素,如下图第一个示例中的a内部的整型是不可变的,内部嵌套的列表是可变的),内存地址也会直接引用过来。

# 不可变数据类型a=[1,2,3,4,5,6]print('a的内存地址为:',id(a))b=aprint('b的内存地址为:',id(a))b[0]=5print('修改b[0]的值后a的值为:',a)print('修改b的值后a的内存地址为:',id(a))print('修改b[0]的值后b的值为:',b)print('修改b的值后b的内存地址为:',id(a))a的内存地址为:2661007521408b的内存地址为:2661007521408修改b[0]的值后a的值为:[5,2,3,4,5,6]修改b的值后a的内存地址为:2661007521408修改b[0]的值后b的值为:[5,2,3,4,5,6]修改b的值后b的内存地址为:2661007521408#可变数据类型a=[1,2,3,[1,2,3],4,5,6]print('a的内存地址为:',id(a))b=aprint('b的内存地址为:',id(a))b[3]=[1,1,3]print('修改b[0]的值后a的值为:',a)print('修改b的值后a的内存地址为:',id(b))print('修改b[0]的值后b的值为:',b)print('修改b的值后b的内存地址为:',id(b))a的内存地址为:2255144316352b的内存地址为:2255144316352修改b[3]的值后a的值为:[1,2,3,[1,1,3],4,5,6]修改b[3]的值后a的内存地址为:2255144316352修改b[3]的值后b的值为:[1,2,3,[1,1,3],4,5,6]修改b[3]的值后b的内存地址为:2255144316352

浅拷贝

浅拷贝只会拷贝最外层的内存地址,将拷贝后的值重新分配内存空间,内部的可变数据类型的数据还是引用的原来的。因此,对于不可变数据数据类型,如果浅拷贝后更改数据,原数据不会发生变化;对于可变数据类型,更改内部的数据后,原数据也会跟着发生变化

# 修改不可变数据类型的值a=[1,2,3,[1,2,3],4,5,6]print('a的内存地址为:',id(a))b=copy.copy(a)print('b的内存地址为:',id(b))b[0]=5print('修改b[0]的值后a的值为:',a)print('修改b的值后a的内存地址为:',id(a))print('修改b[0]的值后b的值为:',b)print('修改b的值后b的内存地址为:',id(b))a的内存地址为:1967541742656b的内存地址为:1967541742912#浅拷贝将拷贝后的值重新分配内存空间修改b[0]的值后a的值为:[1,2,3,[1,2,3],4,5,6]# 修改的是整型,所以a的值不变修改b的值后a的内存地址为:1967541742656修改b[0]的值后b的值为:[5,2,3,[1,2,3],4,5,6]# 变的只有b的值修改b的值后b的内存地址为:1967541742912#修改整个可变数据类型的值,原对象不受影响a=[1,2,3,[1,2,3],4,5,6]print('a的内存地址为:',id(a))b=copy.copy(a)print('b的内存地址为:',id(b))b[3]=[1,1,5]# 将b[3]的整个值给替换了,print('修改b[0]的值后a的值为:',a)print('修改b的值后a的内存地址为:',id(a))print('修改b[0]的值后b的值为:',b)print('修改b的值后b的内存地址为:',id(b))a的内存地址为:2258999209408b的内存地址为:2258999209600修改b[0]的值后a的值为:[1,2,3,[1,2,3],4,5,6]修改b的值后a的内存地址为:2258999209408修改b[0]的值后b的值为:[1,2,3,[1,1,5],4,5,6]修改b的值后b的内存地址为:2258999209600# 只修改嵌套列表中的其中一个元素的值,原列表会跟着变化a=[1,2,3,[1,2,3],4,5,6]print('a的内存地址为:',id(a))b=copy.copy(a)print('b的内存地址为:',id(b))b[3][0]=0print('修改b[0]的值后a的值为:',a)print('修改b的值后a的内存地址为:',id(a))print('修改b[0]的值后b的值为:',b)print('修改b的值后b的内存地址为:',id(b))a的内存地址为:2184038935616b的内存地址为:2184038935872修改b[0]的值后a的值为:[1,2,3,[0,2,3],4,5,6]修改b的值后a的内存地址为:2184038935616修改b[0]的值后b的值为:[1,2,3,[0,2,3],4,5,6]修改b的值后b的内存地址为:2184038935872

上述,在将b[3] 完全替换和只修改其中一个值,引起的a的变化原因是:在b=copy.copy(a)后,虽然b将[1,2,3,[1,2,3],4,5,6]整个列表重新放在了另一个存储空间中,但是浅拷贝只复制对象本身,也就是只复制最外面的一层,a和b里面的[1,2,3]指向的还是同一个内存地址。在将b[3]完全替换为[1,1,3]后,这是另一个列表,和[1,2,3]指向的不再是同一个内存地址,所以a不会变化。但是如果只修改b[3][0]=0,是直接对[1,2,3]这个内存地址进行的修改,所以a会跟着变化

深拷贝

深拷贝和浅拷贝一样,也会将拷贝后的数据放到另一个存储空间中,不同的是,深拷贝递归复制所有子对象,完全独立。也就是说,无论如何修改b的值,a的值都不会变。

# 修改不可变数据,只改变b,不会改变aa=[1,2,3,[1,2,3],4,5,6]print('a的内存地址为:',id(a))b=copy.deepcopy(a)print('b的内存地址为:',id(b))b[0]=0print('修改b[0]的值后a的值为:',a)print('修改b的值后a的内存地址为:',id(a))print('修改b[0]的值后b的值为:',b)print('修改b的值后b的内存地址为:',id(b))a的内存地址为:2298910436544b的内存地址为:2298910436736修改b[0]的值后a的值为:[1,2,3,[1,2,3],4,5,6]修改b的值后a的内存地址为:2298910436544修改b[0]的值后b的值为:[0,2,3,[1,2,3],4,5,6]修改b的值后b的内存地址为:2298910436736#将内部嵌套列表完全修改,只改变b,不会改变aa=[1,2,3,[1,2,3],4,5,6]print('a的内存地址为:',id(a))b=copy.deepcopy(a)print('b的内存地址为:',id(b))b[3]=[1,1,3]print('修改b[0]的值后a的值为:',a)print('修改b的值后a的内存地址为:',id(a))print('修改b[0]的值后b的值为:',b)print('修改b的值后b的内存地址为:',id(b))a的内存地址为:2329156546048b的内存地址为:2329156546240修改b[0]的值后a的值为:[1,2,3,[1,2,3],4,5,6]修改b的值后a的内存地址为:2329156546048修改b[0]的值后b的值为:[1,2,3,[1,1,3],4,5,6]修改b的值后b的内存地址为:2329156546240#修改内部嵌套列表的其中一个元素,只改变b,不会改变aa=[1,2,3,[1,2,3],4,5,6]print('a的内存地址为:',id(a))b=copy.deepcopy(a)print('b的内存地址为:',id(b))b[3][0]=0print('修改b[0]的值后a的值为:',a)print('修改b的值后a的内存地址为:',id(a))print('修改b[0]的值后b的值为:',b)print('修改b的值后b的内存地址为:',id(b))a的内存地址为:2344290446528b的内存地址为:2344290446720修改b[0]的值后a的值为:[1,2,3,[1,2,3],4,5,6]修改b的值后a的内存地址为:2344290446528修改b[0]的值后b的值为:[1,2,3,[0,2,3],4,5,6]修改b的值后b的内存地址为:2344290446720

总结:
引用:直接复制所有元素,不会放到新的存储空间
浅拷贝:只复制最外层的,内部的嵌套数据共享存储空间
深拷贝:逐层递归复制,所有数据都被放到一个新的存储空间

http://www.jsqmd.com/news/668987/

相关文章:

  • 避开这些坑,你的Android设备才能顺利通过Google认证:XTS测试环境与版本配置指南
  • C语言中常用“计时“方法总结
  • 编排者的时代:从单兵工具到群体智能的认知跃迁
  • 调试LVDS屏别再只改代码了!从屏闪、白屏到触屏漂移,三个实战问题背后的硬件时序原理
  • MATLAB App打包 vs exe打包:我该选哪个?一次讲清两者的区别与适用场景
  • 别再傻傻分不清!用一杯水和一把尺子,5分钟搞懂ADC的LSB与精度
  • 自建 code-server vs CloudStudio:为什么插件不能用?
  • 2026年贵阳AI营销招聘生态全景:从传统销售到智能获客的职业进阶指南 - 精选优质企业推荐官
  • 图像擦除算法研究
  • 平衡二叉树的奥秘:AVLTree高效实现解析
  • 【2024 AGI前沿突破】:斯坦福+DeepMind联合验证的4类自主学习范式对比报告
  • 驾驭 Claude 的智能(Harnessing Claude’s intelligence)
  • 贵阳毕业季求职指南|1200万毕业生涌入,这5类岗位和6家公司最值得关注 - 精选优质企业推荐官
  • TypeScript的template literal types实现SQL查询的类型安全
  • 【AGI军事伦理红区预警】:20年国防科技专家首次公开3大不可逾越的AI作战红线
  • 划时代claude-opus-4-7重磅来袭,DMXAPI平台特惠开放,降低 AI 使用成本
  • NLP学习笔记13:BERT系列模型——从预训练到 RoBERTa 与 ALBERT
  • CREO实战宝典:从阵列到骨架模型,解锁十大经典零件设计全流程(曲柱、风扇叶、齿轮参数化、油缸等)
  • 告别DrawCall卡顿!Unity 2022最新Sprite Atlas图集打包保姆级教程(含旧版本迁移指南)
  • 鸣潮自动化终极指南:如何用ok-ww实现智能自动战斗与资源收集
  • 2026年,泉州创业者资源对接会哪个好用?
  • 贵阳销售岗位火热招聘,这5家企业正在疯狂抢人 - 精选优质企业推荐官
  • c# 获取CAD已加载的线型 并且在对话框的下拉列表显示出来
  • 从STRIDE到EVITA:聊聊车载网络威胁建模中,那个更适合你的安全属性模型
  • 告别龟速下载!Hugging Face预训练模型(BERT/RoBERTa)手动下载与本地加载保姆级教程
  • 贵阳找工作必看:2026年销售岗位大盘点,为什么AI营销和顾问型销售更值得选? - 精选优质企业推荐官
  • 解决VisualStudio2026中文打印报错或者乱码
  • UE4/UE5委托实战避坑:从触发器交互到UI响应,手把手教你四种委托的正确用法
  • 如何快速使用MCA Selector:Minecraft世界编辑完整指南
  • 基于springboot的摄影作品分享活动参与网站