d.p*_*tto 139 python reference list
我们来举个例子吧
a=['help', 'copyright', 'credits', 'license']
b=a
b.append('XYZ')
b
['help', 'copyright', 'credits', 'license', 'XYZ']
a
['help', 'copyright', 'credits', 'license', 'XYZ']
Run Code Online (Sandbox Code Playgroud)
我想在列表'b'中附加值,但列表'a'的值也已更改.
我想我不知道为什么会这样(python通过引用传递列表).
我的问题是"如何通过值传递它,以便附加'b'不会改变'a'中的值?"
phi*_*hag 190
正如官方Python FAQ中所回答:
b = a[:]
Run Code Online (Sandbox Code Playgroud)
joa*_*uin 125
要复制列表,您可以使用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]]
>>>
Run Code Online (Sandbox Code Playgroud)
如果您想要对象的完整副本,则需要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]]
>>>
Run Code Online (Sandbox Code Playgroud)
Kyr*_*Kyr 26
在性能方面,我最喜欢的答案是:
b.extend(a)
Run Code Online (Sandbox Code Playgroud)
检查相关替代方案在性能方面的相互比较:
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
Run Code Online (Sandbox Code Playgroud)
Dar*_*mas 16
此外,你可以这样做:
b = list(a)
Run Code Online (Sandbox Code Playgroud)
这适用于任何序列,甚至那些不支持索引器和切片的序列......
如果要复制一维列表,请使用
b = a[:]
Run Code Online (Sandbox Code Playgroud)
但是,如果a是二维列表,这对您不起作用.也就是说,任何变化都a将反映在中b.在那种情况下,使用
b = [[a[x][y] for y in range(len(a[0]))] for x in range(len(a))]
Run Code Online (Sandbox Code Playgroud)
正如phihag在他的回答中提到的,
b = a[:]
Run Code Online (Sandbox Code Playgroud)
因为切片列表会创建列表的新内存ID(这意味着您不再引用内存中的同一个对象,并且您对其中的更改将不会反映在另一个中,因此将适用于您的情况.)
但是,有一个小问题.如果您的列表是多维的,就像列表中的列表一样,只需切片就不能解决这个问题.在较高维度中进行的更改(即原始列表中的列表)将在两者之间共享.
不要担心,有一个解决方案.模块副本有一个漂亮的复制技术,可以解决这个问题.
from copy import deepcopy
b = deepcopy(a)
Run Code Online (Sandbox Code Playgroud)
无论它包含多少级别的列表,都会复制一个带有新内存ID的列表!
当你这样做b = a,你只需创建另一个指针指向相同的内存一个,这就是为什么当你追加到b,一个变化太大.
你需要创建一个a的副本,并且这样做:
b = a[:]
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
153437 次 |
| 最近记录: |