Python 复制列表的最佳方式是什么?

Python 复制列表的最佳方式是什么?,python,Python,复制列表的最佳方式是什么?我知道以下方法,哪一种更好?还是有别的办法 lst = ['one', 2, 3] lst1 = list(lst) lst2 = lst[:] import copy lst3 = copy.copy(lst) 如果需要浅复制(不复制图元),请使用: 如果要进行深度复制,请使用复制模块: import copy lst2=copy.deepcopy(lst1) 我经常使用: lst2 = lst1 * 1 如果lst1包含其他容器(如其他列表),则应使用复

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

lst = ['one', 2, 3]

lst1 = list(lst)

lst2 = lst[:]

import copy
lst3 = copy.copy(lst)

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

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

import copy
lst2=copy.deepcopy(lst1)
我经常使用:

lst2 = lst1 * 1
如果lst1包含其他容器(如其他列表),则应使用复制库中的deepcopy,如Mark所示


更新:复制

>>> 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])
你可能只看到一个改变了的。。。 我现在将尝试列出一系列列表

>>> 
>>> 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 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试试

>>> 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]]
您也可以这样做:

import copy
list2 = copy.copy(list1)
这应该与Mark Roddy的浅拷贝做相同的事情。

您还可以做:

a = [1, 2, 3]
b = list(a)
我喜欢做:

lst2 = list(lst1)
与lst1[:]相比,相同的习惯用法适用于dicts:

dct2 = dict(dct1)

就性能而言,调用
list()
与切片相比有一些开销。因此,对于短列表,
lst2=lst1[:]
的速度大约是
lst2=list(lst1)
的两倍


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

短列表,[:]是最好的:

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
对于较大的列表,它们大致相同:

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毫米),它们仍然大致相同。

元素不被复制是什么意思?如果元素是可变对象,它们通过引用传递,则必须使用deepcopy来真正复制它们。它只会复制列表中包含的引用。如果列表中的元素包含对另一个对象的引用,则不会复制该对象。10次中有9次你只需要浅拷贝。@sheats看到一个更清晰的方法是:
lst2=list(lst1)
实际上在Python 3K邮件列表上对字典拷贝和列表拷贝进行了相当长的讨论:这里的信息是,对于字典,你可以做d=d。copy()的结果是浅拷贝还是深拷贝?不,使用list()绝对是一种肤浅的复制。试试看,有速度差吗?可以说,当您执行
[:]
时,库足够聪明,可以知道正在进行复制,因此它可能会调用一些本机C代码来执行此操作。使用
list(iterable)
它是否知道/关心iterable已经物化,因此可以有效地复制?那么,使用复制模块获取列表的深度复制是唯一的方法吗?Python的标准功能中没有包含深度复制似乎很奇怪。
copy()
在最后一种情况下不起作用,只要对象中有引用,您就需要
deepcopy()
。我认为您使用
lst1*1
的技巧非常好……但是,很遗憾,粗略分析表明,它的速度至少是
lst1[:]
的两倍,比
copy(last1)
稍快一些。如果我必须在100行代码之间进行一次复制,我就不会麻烦了。只有当它是应用程序的核心部分,并且列表复制很频繁时,我才有可能麻烦。
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