在Python中,深度复制与[每个[:]之间的区别在于List中的每一个]

时间:2016-10-11 11:58:43

标签: python list copy deep-copy

以下是示例代码:

from copy import deepcopy
List = [range(3), range(3), range(3)]
a = deepcopy(List)
b = [each[:] for each in List]

我知道初始化a所需的时间比b的时间要慢,但为什么会这样呢?深度复制和[每个[:]列表中的每一个有什么区别?)为什么深度扫描这么慢?

2 个答案:

答案 0 :(得分:6)

each[:]创建每个嵌套列表的副本。 copy.deepcopy()会制作副本。

在这种特殊情况下,嵌套列表包含不可变整数,这种差异实际上并不重要; deepcopy()在复制时返回未更改的整数。但是如果嵌套列表中有可变对象,那么deepcopy()将继续创建这些对象的副本,而列表理解则不会。

例如,在复制包含带有词典的列表的列表时会发现不同之处:

>>> from copy import deepcopy
>>> sample = [[{'foo': 'bar'}, {'ham': 'spam'}], [{'monty': 'python'}, {'eric': 'idle'}]]
>>> shallow = [each[:] for each in sample]
>>> deep = deepcopy(sample)
>>> sample[-1][-1]['john'] = 'cleese'
>>> sample
[[{'foo': 'bar'}, {'ham': 'spam'}], [{'monty': 'python'}, {'eric': 'idle', 'john': 'cleese'}]]
>>> shallow
[[{'foo': 'bar'}, {'ham': 'spam'}], [{'monty': 'python'}, {'eric': 'idle', 'john': 'cleese'}]]
>>> deep
[[{'foo': 'bar'}, {'ham': 'spam'}], [{'monty': 'python'}, {'eric': 'idle'}]]

因为deepcopy()操作必须测试嵌套列表中的每个元素,所以它也慢;如果您知道不需要生成“更深层”的副本,那么列表理解是更好的选择。

答案 1 :(得分:1)

正如Martijn Pieters所说,每个[:]将通过创建每个嵌套列表的浅表副本来执行。如果列表元素是不可变对象,那么您可以使用它,否则您必须使用复制模块中的深度复制。

可以使用切片操作符完全复制浅层列表结构,而不会产生任何副作用,请查看以下快照:

LIST_1 = ['A','B',['AB','BA']]
print LIST_1
>>> ['A', 'B', ['AB', 'BA']]
LIST_2= LIST_1[:]
print id(LIST_1)
>>> 40427648
print id(LIST_2)
>>> 50932872  
LIST_2[2][1] = "D"
LIST_2[2][0] = "C";

print LIST_2
>>> ['A', 'B', ['C', 'D']] 
print LIST_1
>>> ['A', 'B', ['C', 'D']] 

然而在深度镜方法中:

所述问题的解决方案是使用模块" copy"。该模块提供了方法" copy",它允许任意列表的完整副本,即浅表和其他列表。所以你使用copy.deepcopy(...)进行深度复制列表:

deepcopy(x, memo=None, _nil=[])

以下脚本使用上面的示例和此方法:

from copy import deepcopy

LIST_1 = ['A','B',['AB','BA']]

LIST_2= deepcopy(LIST_1)

LIST_2[2][1] = "D"
LIST_2[0] = "C";

print LIST_2
>>>['C', 'B', ['AB', 'D']]
print LIST_1
>>>['A', 'B', ['AB', 'BA']]

enter image description here

因此,每个嵌套列表的浅表副本不会递归地复制内部对象。它只复制最外面的列表,同时仍然引用前一个变量的内部列表,这就是深度复制速度较慢的原因。

相关问题