微信号:gh_1cb598337696

介绍:Qtest,是360公司唯一的服务端测试团队.我们的理念是做一个会编程的测试工程师,做一个不断思考,全力保证产品质量的测试工程师.

浅析Python中的深浅拷贝

2018-06-13 18:55 wendy

点击蓝字关注这个神奇的公众号~

背景介绍


在了解python中深拷贝和浅拷贝之前,我们还是要花一点时间来了解一下python内存中变量的存储情况。对于python而言,python的一切变量都是对象,变量的存储,采用了引用语义的方式,存储的只是一个变量的值所在的内存地址,而不是这个变量的值本身。最简单的如下图所示:



Python中的对不同类型的数据深浅拷贝也不同,主要分两种,一种是数字和字符串,另一种就是列表、元组、字典等其他类型,下面通过字符串和列表的例子来介绍一下有什么不同。


赋值


对象的赋值其实就是对象的引用。当创建一个对象,把它赋值给另一个变量的时候,python并没有拷贝这个对象,只是拷贝了这个对象的引用而已。


下面一段代码我们想实现给字符串和列表中的字符串分别加个后缀,通过这个来看看对不同类型的数据的赋值的区别以及存在的问题,代码如下所示:


结果:


从上图可以看出,对于赋值操作,绿色框的横向对比,两种类型的数据进行赋值后地址没有变化,都是对同一地址的引用;但是红色框的纵向对比发现字符串加后缀后地址发生变化,每次循环加的后缀也不同,但是列表中的字符串重复添加,地址也没有变化。


这是因为对于同一个字符串,python并不会开辟一块新的内存空间,而是维护同一块内存地址;而对于列表,赋值只是对同一对象的引用,存储地址不变化。如果希望列表中字符串也发生变化,可以使用浅拷贝来实现。


浅拷贝


浅拷贝:拷贝了最外围的对象本身,内部的元素都只是拷贝了一个引用而已。也就是,把对象复制一遍,但是该对象中引用的其他对象我不复制,也就是只拷贝第一层地址。将赋值修改为浅拷贝后,如下图所示:

结果:


从上图可以看出,对于浅拷贝操作,绿色框的横向对比,字符串的赋值后地址没有变化,但是列表的发生了变化;通过红色框的纵向对比发现字符串和k1的后缀发送了变化,但是库k3中的字符串出现了和之前k1相同的问题。如果想改变上述情况,希望列表中库k3字符串也发生变化,可以使用深拷贝来实现。


深拷贝


深拷贝:外围和内部元素都进行了拷贝对象本身,而不是引用。也就是,把对象复制一遍,并且该对象中引用的其他对象我也复制。不管嵌套多少层,都会拷贝多少层出来,但是最底层的数字和字符串地址不变。


结果:


从上图可以看出,对于深拷贝操作,绿色框的横向对比,字符串的赋值后地址没有变化,但是列表的发生了变化,但是红色框的纵向对比发现字符串和k1、k3的后缀都发送了变化。 


总结


对于不可变类型的对象,赋值、深浅拷贝最终的地址值和值都是相等的,如果修改对象后,会自动分配新的空间。对于可变类型,赋值不改变地址,是对原对象的引用;而深浅拷贝都是对源对象的复制,会占用不同的内存空间,复制的层次略有区别。欢迎大家批评指正~






Qtest是360旗下的专业测试团队!

是WEB平台部测试技术平台化、效率化的先锋力量!

陪伴是最长情的告白

每日为你推送最in的测试技术

识别二维码

关注我们


 
Qtest之道 更多文章 数据库恢复不了? 不存在的! 一起走进互动直播 福利又双叒叕来啦|DevOps 风向标!DevOps 国际峰会扬帆起航 算法测试探索(二) 面试那些事儿
猜您喜欢 应用程序老出错?只需三步交付品质应用! Docker基础技术:AUFS DaoCloud Enterprise 2.6 与 DaoCloud Pipe 从数据交易走向服务交换,金融大数据未来模式探索 技术大牛第一式 - 重构