在Python中,赋值语句不会拷贝对象,而是在变量和对象之间建立绑定.对于可变集合或包含可变项的集合,有时候需要一个副本,这样就可以在不改变原有数据的情况下改变一个副本.copy模块提供了浅拷贝(shallow copy)和深拷贝(deep copy)操作.
接口如下:
copy.copy(x) # 返回x的浅拷贝 copy.deepcopy(x) # 返回x的深拷贝
浅拷贝与深拷贝之间的区别仅与复合对象(包含其他对象的对象,如list或class)有关:
- 浅拷贝构造一个新的复合对象,然后(尽可能地)把引用插入到这个对象中,该引用指向被原对象包含的其他对象.
- 深拷贝构造一个新的复合对象,然后递归地把原对象中成员的拷贝插入到这个对象中,该拷贝是被原对象包含的其他对象的副本.
对于深拷贝,常常有两个问题存在:
- 递归对象(直接或间接地包含对自身引用的对象)可能会导致递归循环.
- 深拷贝会拷贝太多东西,例如本应该要共享的数据.
deepcopy()函数通过以下方式避免这些问题:
- 维护一个”备忘录”字典,用来记录在当前拷贝过程中已被拷贝过的对象;
- 允许用户定义的class重载拷贝操作.
对于字典类型的dict.copy()方法,以及通过对整个列表的分片(例如,copied_list = original_list[:]),均为浅拷贝.
对于一个class,可以通过定义copy()和deepcopy()来实现它自己的拷贝操作.前者在实现浅拷贝操作时被调用,且无需被传递额外的参数.后者在实现深拷贝操作时被调用,且会被传递一个参数,即”备忘录”字典;如果deepcopy()需要对一个class成员进行深拷贝,则需要以该成员作为第一个参数,以”备忘录”字典作为第二个参数来调用deepcopy().