python list by value not by reference
让我们举个例子
1 2 3 4 5 6 7 | a=['help', 'copyright', 'credits', 'license'] b=a b.append('XYZ') b ['help', 'copyright', 'credits', 'license', 'XYZ'] a ['help', 'copyright', 'credits', 'license', 'XYZ'] |
我想在列表"b"中附加值,但列表"a"的值也发生了变化。< BR>我想我不知道为什么它是这样的(Python通过引用传递列表)。< BR>我的问题是"我如何通过值传递它,以便附加"b"不会更改"a"中的值?"
正如官方python常见问题解答中所回答的:
1 | b = a[:] |
要复制列表,您可以使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | >>> 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | >>> 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]] >>> |
就性能而言,我最喜欢的答案是:
1 | b.extend(a) |
检查相关备选方案在性能方面如何相互比较:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 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 |
此外,您还可以执行以下操作:
1 | b = list(a) |
这将适用于任何序列,甚至那些不支持索引器和切片的序列…
如果要复制一维列表,请使用
1 | b = a[:] |
但是,如果
1 | b = [[a[x][y] for y in range(len(a[0]))] for x in range(len(a))] |
正如他在回答中提到的,
1 | b = a[:] |
这对您的情况很有用,因为切片列表会创建列表的新内存ID(意味着您不再引用内存中的同一对象,对其中一个对象所做的更改不会反映在另一个对象中。)
但是,有一个小问题。如果您的列表是多维的,就像列表中的列表一样,简单的切片不会解决这个问题。在更高维度中所做的更改,即原始列表中的列表,将在两者之间共享。
别担心,有解决办法。模块复制有一种巧妙的复制技术来解决这个问题。
1 2 3 | from copy import deepcopy b = deepcopy(a) |
将复制具有新内存ID的列表,无论它包含多少级别的列表!
当您执行
您需要创建的副本,操作如下:
1 | b = a[:] |
要创建列表的副本,请执行以下操作:
1 | b = a[:] |
我建议采用以下解决方案:
1 2 | b = [] b[:] = a |
这将把所有元素从A复制到B。副本将是值副本,而不是引用副本。
我发现我们可以使用extend()来实现copy()的函数
1 2 3 4 | a=['help', 'copyright', 'credits', 'license'] b = [] b.extend(a) b.append("XYZ") |
请参阅http://henry.precheur.org/python/copy_list。