从底层分析python中深拷贝和浅拷贝区别

xiaoxiao2021-02-28  28

深浅拷贝在python中经常使用,其区别的外在表现是:

使用浅拷贝,当原容器对象中可变对象中有元素发生变化,拷贝得到的对象也会变化。而使用深拷贝时,不会有这种问题。

听起来有一点难理解,看例子比较直观:

浅拷贝

>>> list1 = [['a', 'b'], 1, 2]

>>> list3 = copy.copy(list1)

>>> list3

[['a', 'b'], 1, 2]

>>> list1[0][0] = 'c' #修改lsit1

>>> list3

[['c', 'b'], 1, 2] #list3也变了

深拷贝

>>> list1 = [['a', 'b'], 1, 2]

>>> list3 = copy.deepcopy(list1)

>>> list1[0][0] = 'c' #修改list1

>>> list3

[['a', 'b'], 1, 2] #list3没有变

但是为什么会这样,可以由下图解释:

当我们声明list1 = [['a', 'b'], 1, 2]时,计算机做了这些事:

1、在内存中开辟一段空间,用来存放字符a,b和数字1,数字2

2、在内存开辟一段空间,用来存放一个列表,我们称为list2。list2中存放两个指针,分别指向字符a和b

3、在内存开辟一段空间,用来存放一个列表lsit1,list1中存放三个指针,分别指向list2,数字1和数字2

当执行浅拷贝lsit3 = copy.copy(list1)时,计算机开辟一段内存给list3,list3保存三个指针,分别指向list2,数字1和数字2。当执行list1[0][0] = 'c'时,list2对象修改了,而list3的第一个指针指向list2,所以我们看到list3的第一个元素也变了。

当执行深拷贝lsit4 = copy.copy(list1)时,计算机开辟一段内存给list4,和浅拷贝不同的是,计算机同时开辟一段空间给新的列表,我们称为lsit5。list5中保存2个指针,分别指向字符a和b。

同时list4保存三个指针,分别指向list5,数字1和数字2。此时,当执行list1[0][0] = 'c'时,list2对象修改了,但list4的第一个指针指向list5,list5并没有修改,所以list4没有改变。

总结:深拷贝会把可变对象也拷贝一份,而浅拷贝不会。

上面例子中说的是列表(可变对象)的拷贝,那对于元组,字符等不可不对象呢?

答案是,对不可不对象,其实不存在深浅拷贝的问题。无论怎么拷贝,效果都是新建立一个指向不可变对象的指针而已。

>>> a = 'f'

>>> b = copy.copy(a)

>>> id(a)

4302389968

>>> id(b)

4302389968

>>> c = copy.deepcopy(a)

>>> id(c)

4302389968

>>> 

>>> d = a

>>> id(a)

4302389968

转载请注明原文地址: https://www.6miu.com/read-2629299.html

最新回复(0)