python的浅拷贝与深拷贝

什么是浅拷贝?

先看一个例子

a = [1,2,3,4]
b = a
a.pop(0)
print(a)
print(b)

输出:

[2,3,4]
[2,3,4]

正常对于这种可变对象的这种赋值,会导致 a和b指向一个内存地址,而我们将a中的第0个元素剔除后,实质就是改变了对应的内存地址中的数值,所以会导致b也发生变化
下面看一下浅拷贝:

a = [1,2,3,4]
b = a.copy()
a.pop(0)
print(a)
print(b)

输出

[2,3,4]
[1,2,3,4]

这种就是浅拷贝,拷贝的列表会单独存在另一块内存里面,所以修改原列表中的元素不影响新列表中的元素

什么是深拷贝?

看另一个例子

a = [[1,2],2,3]
b = a.copy()
a[0].pop(0)
print(a)
print(b)

输出:

[[2], 2, 3]
[[2], 2, 3]

为什么我拷贝了原列表,新的列表还是随着原列表改变而改变了?
细心的人会发现,这种改变是改变了列表中的子元素中的内容,而不是只改变了列表
浅拷贝只是将被拷贝的元素存在单独一块内存,但是不能将拷贝元素中的子元素还单独存在一块内存

下面我们用深拷贝:

import copy
a = [[1,2],2,3]
b = copy.deepcopy(a)
a[0].pop(0)
print(a)
print(b)

输出:

[[2], 2, 3]
[[1, 2], 2, 3]

深拷贝不仅仅可以使被拷贝的对象存在单独一个地址中,而且被拷贝的子元素也单独存在一个地址中,是真正的完全拷贝

其他问题

列表中的不可变对象如:数字,字符串,元祖,这些使用深拷贝也会单独分配一块内存吗?由于这些是不可变对象,我们无法使用改变内存中的值来看到效果,但是我们可以通过id()这个函数来查看判断是否存储在同一块内存

import copy
a = [1,2,3]
b = copy.deepcopy(a)
print(id(a[0]))
print(id(b[0]))

输出:

10914496
10914496

结果让人大跌眼睛,这个和我们预想不一样了
其实这是python内部做的优化,对于这些不可变对象,如果元素的值相同,python都会将他们存储在同一块内存以节约内存,因为这些是不可变对象,将他们存在同一块内存不会导致改变一个对象的值导致另一个对象值的变化,所以可以将他们存在同一块内存,这就是python中的inter机制

posted @ 2019-09-19 14:43  Hello_wshuo  阅读(29)  评论(0编辑  收藏  举报