python-深拷贝与浅拷贝
1.可变对象与不可变对象
要想区分python的深拷贝与浅拷贝,首先要区分python的可变对象与不可变对象。这个在我的上一篇python笔记中,已经有所阐述。
- 可变对象包括字典(dictionary)、列表(list)。
- 不可变对象包括int、字符串(string)、浮点型(float)、数值型(number)、元组(tuple)。
- 对不可变对象的连接、替换、去除等操作将产生新的对象。
- 对可变对象的操作可能产生新的对象,也可能不产生新的对象。
2.对象赋值、浅拷贝、深拷贝
关于这三个概念的区别,我这里只写结论,如果想看具体的例子,可以参考这一篇博客(http://www.cnblogs.com/wilber2013/p/4645353.html)。
- 在考虑对象赋值、浅拷贝和深拷贝的相关问题时,一定要考虑它们在内存中的存储情况
- 首先,拷贝的说法只针对容器类型,对于非容器类型(如数字、字符串、和其他’原子’类型的对象)没有拷贝的所法。
- 如果元祖变量只包含原子类型对象,不能对其进行深拷贝(即对其深拷贝不会产生新的对象)。
①对象赋值(Object1 = Object2)
- 并不会创建新的对象,仅仅创建一个引用,指向相同的对象。
- 由于两个引用指向的是相同的对象,所以对一个引用指向对象的操作(无论是对可变对象的操作还是对不可变对象的操作)会影响另外一个引用所指向的对象。
②浅拷贝(Object1 = copy.copy(Object2))
- 首先,浅拷贝会得到一个新的对象。
- 在内存中,新的对象中的元素并不会重新创建,而是仍然利用原有对象中的元素(新对象元素的引用指向原对象的元素)。
- 对某个对象的某个元素进行操作(连接、替换、去除等)时,
- 如果该元素是不可变对象,则该操作不会影响到另外一个对象(因为此时内存中创建了一个新的元素对象,而另外一个对象的元素仍然指向旧的元素对象);
- 如果该元素是可变对象,则该操作会影响到另外一个对象(因为此时内存中没有创建新的对象,只是对原有元素对象进行了改变,而两个对象均有指向该元素的引用)。
使用下面的操作的时候,会产生浅拷贝的效果:
- 使用切片[:]操作
- 使用工厂函数(如list/dir/set)
- 使用copy模块中的copy()函数
③深拷贝(Object1 = copy.deepcopy(Object2))
- 深拷贝也会创建一个新对象
- 对象中的元素,如果是可变对象的话就会被重新创建;如果是不可变对象的话就先不会被重新创建(由于是不可变对象,为了节省内存,没有重建的必要)。
- 对某个对象的某个元素进行操作(连接、替换、去除等)时,均不会影响到另外一个对象的元素:
- 如果进行操作的元素是不可变对象,由于在内存中二者指向的是不同的元素对象,所以对一个对象元素的改变并不会影响到另外一个对象;
- 如果进行操作的元素是可变对象,则产生改变的对象会创建一个新的元素对象并指向它,而另外一个对象不受其影响。
最后,还想再次重申,如果在对象赋值、浅拷贝、深拷贝的问题上产生疑惑,一定要考虑在操作过程中,对象在内存中的存储状况。