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