我们举一个例子
a=['help', 'copyright', 'credits', 'license']
b=a
b.append('XYZ')
b
['help', 'copyright', 'credits', 'license', 'XYZ']
a
['help', 'copyright', 'credits', 'license', 'XYZ']
我想在列表'b'中附加值,但列表'a'的值也已更改。
我想我不知道为什么会这样(python通过引用传递列表)。
我的问题是“如何通过值传递它,以便附加'b'不会改变'a'中的值?”
答案 0 :(得分:172)
b = a[:]
答案 1 :(得分:121)
要复制列表,您可以使用list(a)
或a[:]
。在这两种情况下都会创建一个新对象
但是,这两种方法对可变对象的集合有限制,因为内部对象保持其引用不变:
>>> a = [[1,2],[3],[4]]
>>> b = a[:]
>>> c = list(a)
>>> c[0].append(9)
>>> a
[[1, 2, 9], [3], [4]]
>>> c
[[1, 2, 9], [3], [4]]
>>> b
[[1, 2, 9], [3], [4]]
>>>
如果您需要对象的完整副本,则需要copy.deepcopy
>>> from copy import deepcopy
>>> a = [[1,2],[3],[4]]
>>> b = a[:]
>>> c = deepcopy(a)
>>> c[0].append(9)
>>> a
[[1, 2], [3], [4]]
>>> b
[[1, 2], [3], [4]]
>>> c
[[1, 2, 9], [3], [4]]
>>>
答案 2 :(得分:25)
就性能而言,我最喜欢的答案是:
b.extend(a)
检查相关备选方案在性能方面的相互比较:
In [1]: import timeit
In [2]: timeit.timeit('b.extend(a)', setup='b=[];a=range(0,10)', number=100000000)
Out[2]: 9.623248100280762
In [3]: timeit.timeit('b = a[:]', setup='b=[];a=range(0,10)', number=100000000)
Out[3]: 10.84756088256836
In [4]: timeit.timeit('b = list(a)', setup='b=[];a=range(0,10)', number=100000000)
Out[4]: 21.46313500404358
In [5]: timeit.timeit('b = [elem for elem in a]', setup='b=[];a=range(0,10)', number=100000000)
Out[5]: 66.99795293807983
In [6]: timeit.timeit('for elem in a: b.append(elem)', setup='b=[];a=range(0,10)', number=100000000)
Out[6]: 67.9775960445404
In [7]: timeit.timeit('b = deepcopy(a)', setup='from copy import deepcopy; b=[];a=range(0,10)', number=100000000)
Out[7]: 1216.1108016967773
答案 3 :(得分:16)
另外,你可以这样做:
b = list(a)
这适用于任何序列,即使那些不支持索引器和切片的序列......
答案 4 :(得分:8)
如果要复制一维列表,请使用
b = a[:]
但是,如果a
是一个二维列表,那么这对你不起作用。也就是说,a
中的任何更改也会反映在b
中。在这种情况下,请使用
b = [[a[x][y] for y in range(len(a[0]))] for x in range(len(a))]
答案 5 :(得分:6)
正如phihag在回答中提到的那样,
b = a[:]
将适用于您的情况,因为切片列表会创建列表的新内存ID(意味着您不再引用内存中的同一对象,而您对其中的更改将不会反映在另一个中。)< / p>
然而,有一个小问题。如果您的列表是多维的,就像列表中的列表一样,只需切片就不能解决这个问题。更高维度所做的更改,即原始列表中的列表,将在两者之间共享。
不要烦恼,有一个解决方案。模块副本有一个漂亮的复制技术来处理这个问题。
from copy import deepcopy
b = deepcopy(a)
无论它包含多少级别的列表,都会复制一个带有新内存ID的列表!
答案 6 :(得分:5)
要创建列表副本,请执行以下操作:
b = a[:]
答案 7 :(得分:5)
执行b = a
时,只需创建另一个指向 a 内存的指针,
这就是为什么当你追加 b , a 也会改变。
您需要创建 a 的复制,并且这样做:
b = a[:]
答案 8 :(得分:2)
我发现我们可以使用extend()来实现copy()
的功能a=['help', 'copyright', 'credits', 'license']
b = []
b.extend(a)
b.append("XYZ")
答案 9 :(得分:2)
我会推荐以下解决方案:
b = []
b[:] = a
这会将a中的所有元素复制到b。副本将是价值副本,而不是参考副本。
答案 10 :(得分:1)
b = list(a)