Вопрос-Ответ

python list by value not by reference [duplicate]

список 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'?"

Переведено автоматически
Ответ 1

Вы не можете передавать что-либо по значению в Python. Если вы хотите создать копию a, вы можете сделать это явно, как описано в официальном FAQ по Python:

b = a[:]
Ответ 2

Для копирования списка вы можете использовать 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]]
>>>
Ответ 3

С точки зрения производительности моим любимым ответом было бы:

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
Ответ 4

Кроме того, вы можете сделать:

b = list(a)

Это будет работать для любой последовательности, даже для тех, которые не поддерживают индексаторы и срезы...

python list