python按值列表不是通过引用
我们来举个例子
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'中的值?
正如在Python官方FAQ中回答的那样:
b = a[:]
要复制列表,您可以使用list(a)
或a[:]
。 在这两种情况下都会创build一个新的对象。
但是,这两种方法对可变对象的集合有限制,因为内部对象保持其引用的完整性:
>>> 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]] >>>
在性能方面,我最喜欢的答案是:
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
另外,你可以做:
b = list(a)
这将适用于任何序列,即使那些不支持索引器和片…
要创build列表的副本,请执行以下操作:
b = a[:]
当你做b = a
你只需要创build另外一个指向a的同一个内存的指针,这就是为什么当你追加到b时也会有一些变化。
你需要创build一个和这样做的副本 :
b = a[:]
如果您想复制一维列表,请使用
b = a[:]
但是,如果a是二维列表,这不适用于你。 也就是说,a中的任何变化都会反映在b中。 在这种情况下,使用
b = [[a[x][y] for y in range(len(a[0]))] for x in range(len(a))]
正如phihag在他的回答中提到的那样,
b = a[:]
将适用于你的情况,因为切片列表会创build列表的新内存ID(这意味着您不再引用内存中的同一个对象,并且对其中一个进行的更改不会反映在其他内存中)。
但是,有一个小问题。 如果你的列表是多维的,就像列表中的列表一样,简单的切片就不能解决这个问题。 更高维度的更改,即原始列表内的列表将在两者之间共享。
不要担心,有一个解决scheme。 模块副本有一个漂亮的复制技术,照顾这个问题。
from copy import deepcopy b = deepcopy(a)
将复制一个新的内存ID列表,无论它包含多less级别的列表!
我发现我们可以使用extend()来实现copy()的function
a=['help', 'copyright', 'credits', 'license'] b = [] b.extend(a) b.append("XYZ")
b = list(a)