关于python:复制列表的最佳方法是什么?

What is the best way to copy a list?

本问题已经有最佳答案,请猛点这里访问。

复制列表的最佳方法是什么?我知道以下哪种方法更好?还是有别的办法?

1
2
3
4
5
6
7
8
lst = ['one', 2, 3]

lst1 = list(lst)

lst2 = lst[:]

import copy
lst3 = copy.copy(lst)

如果需要浅复制(不复制元素),请使用:

1
lst2=lst1[:]

如果要进行深度复制,请使用复制模块:

1
2
import copy
lst2=copy.deepcopy(lst1)


我经常使用:

1
lst2 = lst1 * 1

如果lst1包含其他容器(如其他列表),则应使用复制库中的deepcopy,如mark所示。

更新:解释deepcopy

1
2
3
4
5
6
7
>>> a = range(5)
>>> b = a*1
>>> a,b
([0, 1, 2, 3, 4], [0, 1, 2, 3, 4])
>>> a[2] = 55
>>> a,b
([0, 1, 55, 3, 4], [0, 1, 2, 3, 4])

你可能只看到一个变化…我现在就用列表试试

1
2
3
4
5
6
7
>>>
>>> a = [range(i,i+3) for i in range(3)]
>>> a
[[0, 1, 2], [1, 2, 3], [2, 3, 4]]
>>> b = a*1
>>> a,b
([[0, 1, 2], [1, 2, 3], [2, 3, 4]], [[0, 1, 2], [1, 2, 3], [2, 3, 4]])

不太可读,让我用"for:

1
2
3
4
5
6
7
8
>>> for i in (a,b): print i  
[[0, 1, 2], [1, 2, 3], [2, 3, 4]]
[[0, 1, 2], [1, 2, 3], [2, 3, 4]]
>>> a[1].append('appended')
>>> for i in (a,b): print i

[[0, 1, 2], [1, 2, 3, 'appended'], [2, 3, 4]]
[[0, 1, 2], [1, 2, 3, 'appended'], [2, 3, 4]]

看到了吗?它也附加到b[1]上,所以b[1]和a[1]是非常相同的对象。现在用deepcopy试试看

1
2
3
4
5
6
7
>>> from copy import deepcopy
>>> b = deepcopy(a)
>>> a[0].append('again...')
>>> for i in (a,b): print i

[[0, 1, 2, 'again...'], [1, 2, 3, 'appended'], [2, 3, 4]]
[[0, 1, 2], [1, 2, 3, 'appended'], [2, 3, 4]]


您还可以执行以下操作:

1
2
a = [1, 2, 3]
b = list(a)


我喜欢这样做:

1
lst2 = list(lst1)

相对于lst1[:]的优势在于,相同的习惯用法适用于听写:

1
dct2 = dict(dct1)


短名单,[:]是最好的:

1
2
3
4
5
6
7
8
9
10
In [1]: l = range(10)

In [2]: %timeit list(l)
1000000 loops, best of 3: 477 ns per loop

In [3]: %timeit l[:]
1000000 loops, best of 3: 236 ns per loop

In [6]: %timeit copy(l)
1000000 loops, best of 3: 1.43 us per loop

对于更大的列表,它们几乎是相同的:

1
2
3
4
5
6
7
8
9
10
In [7]: l = range(50000)

In [8]: %timeit list(l)
1000 loops, best of 3: 261 us per loop

In [9]: %timeit l[:]
1000 loops, best of 3: 261 us per loop

In [10]: %timeit copy(l)
1000 loops, best of 3: 248 us per loop

对于非常大的列表(我尝试了50毫米),它们仍然大致相同。


您也可以这样做:

1
2
import copy
list2 = copy.copy(list1)

这应该和马克·罗迪的浅薄的作品一样。


在性能方面,与切片相比,调用list()有一些开销。因此,对于短名单,lst2 = lst1[:]的速度大约是lst2 = list(lst1)的两倍。

在大多数情况下,这可能会被list()更具可读性这一事实所压倒,但在紧凑的循环中,这可能是一个有价值的优化。