背景

在运用Python进行开发代码过程中,会遇到变量复制备份的场景,但并没有得到预期的结果,例如下面的例子:

lista = ['a', 'b', [1, 2, 3]]
listb = lista.copy()
lista[2].append(4)print(lista)  # ['a', 'b', [1, 2, 3, 4]]
print(listb)  # ['a', 'b', [1, 2, 3, 4]]

代码本意是将lista复制给listb做个备份,再修改liasta,但是修改后发现listb也一并被修改了,没有达到备份的效果,这个是什么原因呢?

存储方式

首先了解一下Python的变量在内存中的存储方式。在基本数据类型中(包括set、list(tuple, str)、dict)都是采用引用的方式。

也就是说,每个变量都存储的是这个变量的地址,而不是值本身,就算更复杂的嵌套结构,也是存储是每个元素的地址而已,用一幅图来表示。

如上图所示,用户看到的是 lista的4个元素值,但是内存中保存的却是4个元素地址。

当元素是列表时,第一层保存的是列表的地址,第二层保存的是列表元素的地址,第三层才是列表的值。当元素是字典的时候,与列表类似。

列表的增删改

在明白了变量存储方式后,继续看下内存下的增删改是怎么变化的。

列表修改已有值

新增一个内存块,再将引用的地址修改为新内存块的地址。

列表新增一个值

新增一个内存块,新增一个地址引用。

列表整体重新赋值

删除变量地址和引用的值,新增地址和引用值的内存块。

copy与deepcopy的区别

基于以上的理解,再来看两种copy的区别就会更容易理解了,首先记住一个原则:
copy:不管多么复杂的数据结构,浅拷贝都只会copy一层。

deepcopy:将整个变量内存全部复制一遍,新变量与原变量没有任何关系。

举个例子来验证一下上面的结论:有如下的一段代码,最终的4个列表值是多少?

注意:引用deepcopy需要导入copy库。

import copya = [1, 2, 3, 4, ['a', 'b']]
b = a
c = copy.copy(a)
d = copy.deepcopy(a)a.append(5)
a[1] = 20
a[4].append('c')
del a[0]print(a)
print(b)
print(c)
print(d)

列表b

表示b也引用的a的地址,两者引用的内存地址是一样的。因此b和a的关系是紧密相连的,一模一样。可以通过 id(a) 和id(b)比较,两者是一样的。

列表c

由于c是浅拷贝的a列表,因此只copy了第一层,也就是地址层。

所以,当a.append(5)时,新增了一个内存块,但是c只有前5个内存块,因此c没有变化。

继续a修改了a[1],然而这个值是属于第一层,已经copy给了c,因此c也没有变化。

继续a修改了子列表,这个时候a复制给c的只是列表的地址,且a中的子列表地址和c中的子列表地址是指向同一个地方的,因此修改了a中子列表,c中的子列表也会相应的改变。

最后删除a[0],与修改a[1]一致,与c无关。可以用图再说明一下。

列表d

由于d是深拷贝的a列表,因此d是将a的地址和值一并复制过来,与a没有半点关系,也就是说d和a是两个完全独立的内存块,没有任何交集。因此,后面a的任意修改都与d无关,用图表示如下。

因此,程序运行出来后的结果就是:

a:[20,3,4,[‘a’,‘b’,‘c’],5]
b:[20,3,4,[‘a’,‘b’,‘c’],5]
c:[1,2,3,4,[‘a’,‘b’,‘c’]]
d:[1,2,3,4,[‘a’,‘b’]]

总结

综上,我们在使用copy的时候,一定要记住:copy只是拷贝了第一层,而deepcopy才是拷贝的全部数据。

因此就不难发现,文章背景中的代码使用备份功能时,备份列表需要使用deepcopy,而不是简单的copy。


资源分享

下方这份完整的软件测试视频学习教程已经上传CSDN官方认证的二维码,朋友们如果需要可以自行免费领取 【保证100%免费】

不懂copy与deepcopy的区别?这一篇就够了相关推荐

  1. copy模块中的copy与deepcopy的区别

    前言 每空闲下来,就觉得以前写的博客很low........也许现在也很low~~~~好吧就当升级版的low吧~~~~ 如果要了解copy与deepcopy的区别,就需要了解Python的存储机制:P ...

  2. Python中copy()和deepcopy()的区别

    同样是copy,二者有什么不同呢今天我们就一探究竟!!! 关于copy()和deepcopy()的第一篇博客 初学编程的小伙伴都会对于深浅拷贝的用法有些疑问,今天我们就结合python变量存储的特性从 ...

  3. python中copy和deepcopy的区别_python里shadowcopy和deepcopy的区别

    python中,经常会需要拷贝特定对象,在此可能就会遇到各种bug,原因就是明白这三种操作的区别,赋值,浅拷贝,深拷贝. 赋值(=),浅拷贝(copy)和深拷贝(deepcopy)比较容易区别开的是赋 ...

  4. python中copy和deepcopy详细区别

    python中copy和deepcopy 在 python 中,标识一个对象唯一身份的是:对象的id(内存地址),对象类型,对象值. deepcopy是真正意义上的复制,深拷贝,被复制对象完全复制一遍 ...

  5. python安装copy_python中copy和deepcopy 的区别

    请简述赋值, 深拷贝和浅拷贝的区别?(python中如何拷贝一个对象?) 直接赋值(li1 = li): 只传递对象的引用, li1指向对象li的内存地址空间, 因此, 原有列表li改变, 被赋值的l ...

  6. copy与deepcopy的区别

    1. copy() copy()用来复制列表或字典里的值,而不是复制它们的引用.但是copy()只能复制单纯的.不包含子列表的列表. a=[1,2,3] copyList=a.copy() print ...

  7. python deepcopy_【Python】copy和deepcopy的区别

    [人生苦短,我用Python] 直入主题,在Python中,我们常常用到copy这个关键字,对于之前做iOS开发的我来说Python中的深拷贝和浅拷贝和iOS中的深浅拷贝还是有一些区别的. 浅拷贝是对 ...

  8. python中copy什么意思_python中copy与deepcopy的区别

    spring MVC入门教程 写一个spring mvc后台传值到前台的一个小例子. 分为以下几个步骤: 1.创建web项目. 导入项目包.具体有如下: spring-aop-4.0.4.RELEAS ...

  9. python str输出到txt_Python 速学!不懂怎么入门python的小白看这篇就够了!

    Python是一种非常流行的脚本语言,而且功能非常强大,几乎可以做任何事情,比如爬虫.网络工具.科学计算.树莓派.Web开发.游戏等各方面都可以派上用场.同时无论在哪种平台上,都可以用 Python ...

最新文章

  1. 使用ubuntu(18.04) 作为软路由器连接互联网
  2. linux删除网卡bond,linux下网卡bond的基本配置及错误
  3. linux ftp登录命令_Linux使用pinky命令查询登录用户信息
  4. 基于单目视觉的智能车辆视觉导航系统设计
  5. makefile中的include *******
  6. spring IOC容器 Bean 管理——基于注解方式
  7. FusionCharts-堆栈图、xml格式、刷新数据、添加事件link、传参
  8. OceanBase数据库开发和运维漫谈
  9. 从右边开始放_幸福的生活,从入住新房开始,效果很漂亮,忍不住给大家晒晒全屋...
  10. 让谷歌、百度最快最多地收录您的网站
  11. jsp加载常量的探讨
  12. Windows无法安装到这个磁盘 选中的磁盘具有MBR分区表解决方法
  13. python 传递任意数量的实参
  14. c语言的万能头文件,C/C 头文件太难记?万能头文件全搞定!
  15. iOS YYKit学习之YYText的使用
  16. 如何画好室内手绘效果图,非常值得…
  17. 解决Idea中yml文件不显示小绿叶图标
  18. python def 识别print_Python零基础快速入门(一):print()函数与变量
  19. (FMD)辉芒MCU开发指南
  20. mat后缀名_mat文件扩展名,mat文件怎么打开?

热门文章

  1. 云阅片 微云影像旗下个人医学影像助手
  2. Go :测试简单的布尔和数字常量(附完整源码)
  3. 免费申请极验GEETEST4.0行为验证账号
  4. CTF web安全45天入门学习路线
  5. 苹果称自家的NFC比安卓手机的更安全
  6. JS和JSP之间的区别
  7. 什么是电竞?人们为什么观看它们?
  8. 关于使用docker启动容器失败解决访问
  9. html 学习 常用的html标签及使用
  10. rebar3 简单使用