51Testing软件测试论坛

 找回密码
 (注-册)加入51Testing

QQ登录

只需一步,快速开始

微信登录,快人一步

手机号码,快捷登录

查看: 737|回复: 0
打印 上一主题 下一主题

[原创] copy与deepcopy的区别看完这篇就够了

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2022-11-7 15:02:52 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
背景

  在运用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 copy



a = [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。

















本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?(注-册)加入51Testing

x
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏
回复

使用道具 举报

本版积分规则

关闭

站长推荐上一条 /1 下一条

小黑屋|手机版|Archiver|51Testing软件测试网 ( 沪ICP备05003035号 关于我们

GMT+8, 2024-9-27 06:11 , Processed in 0.061413 second(s), 24 queries .

Powered by Discuz! X3.2

© 2001-2024 Comsenz Inc.

快速回复 返回顶部 返回列表