深浅拷贝的理解

发布时间:2022-06-21 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了深浅拷贝的理解脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。

深浅拷贝的区别是什么?

1.基本概念

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

浅拷贝:拷贝的是对象的引用,如何原对象改变 ,响应的拷贝对象也会发生改变

深拷贝:拷贝对象中的每个元素,拷贝对象和原对象不再有关系,两个是独立的对象

对于数字和字符串来说,无论通过赋值,浅拷贝还是深拷贝,同一个值永远用的是同一个内存地址,

不会重复在内存中开辟空间。

2.什么是可变对象

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

不可变对象是指,一个对象所指向的地址上值是不能修改的,如果你修改了这个对象的值,那么他指向的 地址上把值给改变了,而这个对象依然只想这个地址

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

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

4.如何实现

说了这么多,到底是如何实现的呢,不要着急,接下来看代码。

import copya=[1,2,3,4,5,['a','b']]#原始对象b=a#赋值,传对象的引用c=copy.copy(a)#对象拷贝,浅拷贝d=copy.deepcopy(a)#对象拷贝,深拷贝print("a=",a,"    id(a)=",id(a),"id(a[5])=",id(a[5]))print("b=",b,"    id(b)=",id(b),"id(b[5])=",id(b[5]))print("c=",c,"    id(c)=",id(c),"id(c[5])=",id(c[5]))print("d=",d,"    id(d)=",id(d),"id(d[5])=",id(d[5]))print("*"*70)a.append(6)#修改对象aa[5].append('c')#修改对象a中的['a','b']数组对象print("a=",a,"    id(a)=",id(a),"id(a[5])=",id(a[5]))print("b=",b,"    id(b)=",id(b),"id(b[5])=",id(b[5]))print("c=",c,"       id(c)=",id(c),"id(c[5])=",id(c[5]))print("d=",d,"            id(d)=",id(d),"id(d[5])=",id(d[5]))

 

a= [1, 2, 3, 4, 5, ['a', 'b']]     id(a)= 1512100200968 id(a[5])= 1512100281096b= [1, 2, 3, 4, 5, ['a', 'b']]     id(b)= 1512100200968 id(b[5])= 1512100281096c= [1, 2, 3, 4, 5, ['a', 'b']]     id(c)= 1512100278408 id(c[5])= 1512100281096d= [1, 2, 3, 4, 5, ['a', 'b']]     id(d)= 1512100119048 id(d[5])= 1512100278600**********************************************************************a= [1, 2, 3, 4, 5, ['a', 'b', 'c'], 6]     id(a)= 1512100200968 id(a[5])= 1512100281096b= [1, 2, 3, 4, 5, ['a', 'b', 'c'], 6]     id(b)= 1512100200968 id(b[5])= 1512100281096c= [1, 2, 3, 4, 5, ['a', 'b', 'c']]        id(c)= 1512100278408 id(c[5])= 1512100281096d= [1, 2, 3, 4, 5, ['a', 'b']]             id(d)= 1512100119048 id(d[5])= 1512100278600

从程序的结果来看,列表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])

但是两个列表的地址是不同的

脚本宝典总结

以上是脚本宝典为你收集整理的深浅拷贝的理解全部内容,希望文章能够帮你解决深浅拷贝的理解所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。
标签: