Copy and Deepcopy in Python
浅拷贝(Copy)
无论浅拷贝还是深拷贝,在使用前都要先导入库copy:
1 | import copy |
对不可变类型的浅拷贝
Python中的不可变数据类型一般指字符串string、数值number和布尔值bool。想要修改引用了不可变数据类型的变量,我们只能让其引用新的对象:
1 | a = 3 |
当浅拷贝了引用不可变数据类型的对象时,浅拷贝相当于赋值操作,即两者会引用同一个不可变对象:
1 | a = 5 |
对可变类型的浅拷贝
Python中的可变类型指列表list、字典dictionary、集合set以及自定义的类。当变量引用可变类型时,该变量相当于拥有了一个袋子,这个袋子里面装的东西可以随便修改,但是只要变量不引用新的袋子,无论怎么修改原来的袋子,原来的袋子始终是原来的袋子。
1 | a = [1, 2, 3] |
当浅拷贝了引用可变数据类型的对象时,Python会直接创造一个新的“袋子”给新对象,但是袋子里的内容与原来的一样:
1 | a = [1, 2, 3] |
这是对于“袋子”里装的是不可变数据类型的情况,若袋子里装的是可变数据类型,如嵌套列表:
1 | a = [[1, 2], 1] |
即,里面的袋子还是同一个。这就是浅拷贝(Copy),它只新创造最外层的“袋子”,但是里面的内容完全不动:引用不可变类型的变量仍引用同一个不可变对象,引用可变类型的变量仍引用同一个“袋子”。
深拷贝(Deepcopy)
对于不可变类型的深浅拷贝,其效果相同,此处不再赘述。
可变类型的深拷贝
当可变类型“袋子”中只有不可变类型的数据时,深拷贝与浅拷贝的效果相同。但是当可变类型“袋子”中也有可变类型时,深拷贝会对“袋子”里面的所有可变类型变量递归地使用深拷贝。也就是说,深拷贝后的两个变量a和b尽管会引用相同的不可变类型对象,但是它们是完全不同的两个变量,修改a完全不会影响b:
1 | a = [[1, 2], 1] |
元组的深浅拷贝
元组本身是不可变的数据类型,因此,它的深浅拷贝应该是一样的。但是,当元组内含有可变类型的对象时,对元组的深拷贝会递归地对该可变类型的对象进行深拷贝,进而导致整个元组被放在新开辟的空间:
1 | tup = (1, [1, 2]) |