BLOG
Enjoy when you can, and endure when you must.
DEC 01, 2013/Python
Python对象拷贝

在Python中,当给一个对象进行赋值、将其作为参数传递或作为结果返回时,总是使用的是一个指向原对象的引用,而不是拷贝。

由此可见,如果确实需要拷贝则需要明确使用“拷贝”的方法来解决。

不过还要注意的是,对象拷贝始终针对的是可变数据类型,对于像字符串、数字、元组等不可变对象是没有必要拷贝的。

Python标准库中的copy模块提供了对象拷贝的方法:

copy.copy()返回一个具有相同的内容和属性的对象,该方法属于浅拷贝,它生成一个新对象,但是对象内部的属性和内容仍引用原对象。

>>> import copy
>>> old_list = range(5)
>>> old_list
[0, 1, 2, 3, 4]
>>> new_list = copy.copy(old_list)
>>> new_list
[0, 1, 2, 3, 4]
>>> old_list.append(6)
>>> old_list, new_list
([0, 1, 2, 3, 4, 6], [0, 1, 2, 3, 4])

刚才已经说过,该方法属于浅拷贝,因此假设有如下情况,使用copy.copy()则可能达不到预期的效果:

>>> old_list = [range(3), range(4)]
>>> old_list
[[0, 1, 2], [0, 1, 2, 3]]
>>> new_list = copy.copy(old_list)
>>> new_list
[[0, 1, 2], [0, 1, 2, 3]]
>>> old_list[0].append(3)
>>> old_list, new_list
([[0, 1, 2, 3], [0, 1, 2, 3]], [[0, 1, 2, 3], [0, 1, 2, 3]])

因为浅拷贝对于对象内部的属性和内容仍引用原对象,因此如上示例中,old_list里面是嵌套列表(可变对象),则对其内部对象进行修改后,也同时会影响通过浅拷贝得到的new_list。因此copy模块中提供另一个方法:copy.deepcopy(),即深拷贝。但因为该方法需要递归地拷贝对象内部的引用对象,因此会更耗内存和时间。

对于浅拷贝,如果知道要拷贝的对象的类型,那么还有另外的方法来实现同样的功能。如对于列表,可以调用list()方法;对于字典则有dict()方法,以此类推。部分对象内建copy()方法,同样是属于浅拷贝。

COMMENTS
LEAVE COMMNT