【python】深拷贝和浅拷贝

来源:互联网 发布:html砸金蛋源码下载 编辑:程序博客网 时间:2024/06/02 11:47

深拷贝和浅拷贝也是python的一个基础知识点,今天好好研究了下,其实深拷贝和浅拷贝问题就是内存中指针的指向问题。我是这么理解的,有不同意见,欢迎指出。

我就不拆开讲了,一起讲,三种情况,一种是直接赋值引用 即b,一种是浅拷贝即c,一种是深拷贝即d。

>>> import copy  #这个需要导入下的 之前还以为是自带的函数报错了 >>> a  = [1,2,[3,4]]>>> b = a #直接赋值>>> c = copy.copy(a) #浅拷贝 c>>> d = copy.deepcopy(a) #深拷贝 d>>> a.append(5)>>> a[1, 2, [3, 4], 5]>>> b[1, 2, [3, 4], 5]>>> c[1, 2, [3, 4]]>>> d[1, 2, [3, 4]]>>> id(a)4432492592>>> id(b)4432492592>>> id(c)4432493024>>> id(d)4432493888#在a后面加了一个值之后可以看到 b随a改变而改变了,而c,d并没有改变,看了他们的id之后,我们发现,b和a指向的是同一个地址,而c,d则是新创建了一个地址。>>> a[2].append(6)>>> a[1, 2, [3, 4, 6], 5]>>> b[1, 2, [3, 4, 6], 5]>>> c[1, 2, [3, 4, 6]]>>> d[1, 2, [3, 4]]>>> id(a[1])140220084269312>>> id(b[1])140220084269312>>> id(c[1])140220084269312>>> id(d[1])140220084269312>>> id(a[2])4432552592>>> id(b[2])4432552592>>> id(c[2])4432552592>>> id(d[2])4432332992#然后我们改变a中的字列表,可以看到,浅拷贝的改变了,但是深拷贝没有改变,我们看他们的id发现,在拷贝的时候,浅拷贝时候,列表中的每个元素直接指向原来列表中a的每个元素的地址,(因为只指向了a之前存在的元素地址,所以在append操作的时候并不会同步)包括子列表(可变的元素),但是对于深拷贝,它自己新建了个地址,递归复制了原来的内容,所以当原来的改变的时候,拷贝的值并没有改变。相同的,如果a[0]改变了,c,d也不会改变,因为a指向了一个新地址,而b,c依然指向原来的地址。

所谓“浅拷贝”,是指创建一个新的对象,其内容是原对象中元素的引用。(拷贝组合对象,不拷贝子对象)
常见的浅拷贝有:切片操作、工厂函数、对象的copy()方法、copy模块中的copy函数。

所谓“深拷贝”,是指创建一个新的对象,然后递归的拷贝原对象所包含的子对象。深拷贝出来的对象与原对象没有任何关联。
深拷贝只有一种方式:copy模块中的deepcopy函数。

看了上面的例子,有人可能会疑惑:
为什么使用了深拷贝,a和b中元素的id还是一样呢?
答:这是因为对于不可变对象,当需要一个新的对象时,python可能会返回已经存在的某个类型和值都一致的对象的引用。而且这种机制并不会影响 a 和 b 的相互独立性,因为当两个元素指向同一个不可变对象时,对其中一个赋值不会影响另外一个。

参考文章
http://blog.csdn.net/lisonglisonglisong/article/details/38573269

0 0