Python 深浅复制
(一)浅复制
复制列表最简单的方式是使用内置类型的构造方法:
>>> l1 = [1, [2, 3], (4, 5)] >>> l2 = list(l1) >>> l2 [1, [2, 3], (4, 5)] >>> l2 is l1 False >>> l2 == l1 True
对于列表和其他可变序列来说,也可以使用[:]:
>>> l3 = l1[:] >>> l3 [1, [2, 3], (4, 5)] >>> l3 is l1 False >>> l3 == l1 True
然而构造方法和[:]都是浅复制,其复制原理如下图所示:
在上面的列表中,有元素是可变的,这可能导致意想不到的问题:
比如我们现在执行语句 l1[1].remove(2)
其结果如下图:
对l1的remove操作同时会影响l2,
我们再试试对l2的的元素操作: l2[1] += [22],其结果如下:
同样的,对l2的操作影响l2.
当我们对l1里的元组进行+=操作后,结果如下:
对于元组来说,它本身是不可变序列, +=运算符创建了一个新元组,然后重新绑定给了变量l1[2], l1, l2中最后位置上的元组不是同一个对象
(二)深复制
默认浅复制没有什么问题,但是有时候我们需要深复制,copy模块提供了deepcopy和copy函数,它们可以为任意对象做深复制和浅复制
下面演示deepcopy和copy的区别:
先定义Bus类如下:
class Bus: def __init__(self, passengers=None): if passengers is None: self.passengers = [] else: self.passengers = list(passengers) def pick(self, name): self.passengers.append(name) def drop(self, name): self.passengers.remove(name)
然后在控制台使用copy和deepcopy分别对Bus类的实例进行操作:
>>> from Example8_8 import Bus >>> import copy >>> bus1 = Bus(['Alice', 'Bill', 'Claire', 'David']) >>> bus2 = copy.copy(bus1) >>> bus3 = copy.deepcopy(bus1)
我们让Alice从bus1下车:
>>> bus1.drop('Alice')
然后在查看bus2和bus3的乘客:
>>> bus2.passengers ['Bill', 'Claire', 'David'] >>> bus3.passengers ['Alice', 'Bill', 'Claire', 'David']
查看对象内存图我们可以明白其中的原理,
Alice下车前,对象内存图如下:
Alice下车后对象内存图如下: