python 深复制和浅复制

时间:2022-08-23 13:08:13
>>> l1 = [1,[2,3],(4,5)]
>>> l2 = list(l1)
>>> l1.append(99)
>>> l1
[1, [2, 3], (4, 5), 99]
>>> l2
[1, [2, 3], (4, 5)]
>>> l1[1].remove(2)
>>> l1
[1, [3], (4, 5), 99]
>>> l2
[1, [3], (4, 5)]
>>> l2[1] += [11, 12]
>>> l2[2] += (10, 11)
>>> l1
[1, [3, 11, 12], (4, 5), 99]
>>> l2
[1, [3, 11, 12], (4, 5, 10, 11)]

复制列表( 或多数内置的可变集合) 最简单的方式是使用内置的类型构造方法。但是二者指代不同的对象。 对列表和其他可变序列来说,还能使用简洁的 l2 = l1[:] 语句创建副本。
这里构造方法或 [:] 做的是浅复制( 即复制了最外层容器, 副本中的元素是源容器中元素的引用)
如果所有元素都是不可变的, 那么这样没有问题, 还能节省内存。 但是, 如果有可变的元素, 可能就会导致上述的问题。
对可变的对象来说, 如 l2[1] 引用的列表, += 运算符就地修改列表。 这次修改在 l1[1] 中也有体现, 因为它是 l2[1] 的别名。
对元组来说, += 运算符创建一个新元组, 然后重新绑定给变量l2[2]。 这等同于 l2[2] = l2[2] + (10, 11)。 现在, l1 和 l2 中最后位置上的元组不是同一个对象


copy 模块提供的 deepcopy 和 copy 函数能为任意对象做深复制和浅复制。

>>> from copy import deepcopy
>>> l1
[1, [3, 11, 12], (4, 5), 99]
>>> l3 = deepcopy(l1)
>>> l3
[1, [3, 11, 12], (4, 5), 99]
>>> l3[1] += [13,14]
>>> l1
[1, [3, 11, 12], (4, 5), 99]
>>> l3
[1, [3, 11, 12, 13, 14], (4, 5), 99]
此外我们可以实现特殊方法 __copy__() 和__deepcopy__(), 控制 copy 和 deepcopy 的行为