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

Changing one list unexpectedly changes another, too [duplicate]

Изменение одного списка неожиданно меняет и другой

У меня есть список вида

v = [0,0,0,0,0,0,0,0,0]

Где-то в коде я делаю

vec=v
vec[5]=5

и это меняет как v , так и vec:

>>> print vec
[0, 0, 0, 0, 0, 5, 0, 0, 0]
>>> print v
[0, 0, 0, 0, 0, 5, 0, 0, 0]

Почему v вообще меняется?

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

Почему v вообще меняется?


vec и v являются ссылками.

При написании кода vec = v вы назначаете v адрес vec. Следовательно, изменение данных в v также "изменится" vec.

Если вы хотите иметь два разных массива, используйте:

vec = list(v)
Ответ 2

Потому что v указывает на тот же список, что и vec в памяти.

Если вы не хотите иметь это, вам нужно создать

from copy import deepcopy
vec = deepcopy(v)

или

vec = v[:]
Ответ 3

Запустите этот код, и вы поймете, почему изменяется переменная v.

a = [7, 3, 4]
b = a
c = a[:]
b[0] = 10
print 'a: ', a, id(a)
print 'b: ', b, id(b)
print 'c: ', c, id(c)

Этот код выводит следующий результат в моем интерпретаторе:

a:  [10, 3, 4] 140619073542552                                                                                                
b: [10, 3, 4] 140619073542552
c: [7, 3, 4] 140619073604136

Как вы можете видеть, списки a и b указывают на одну и ту же ячейку памяти. Тогда как список c - это совершенно другая ячейка памяти. Можно сказать, что переменные a и b являются псевдонимами для одного и того же списка. Таким образом, любое изменение, внесенное в переменную a или b, будет отражено и в другом списке, но не в списке c
Надеюсь, это поможет! :)

Ответ 4

Python указывает оба списка в vec = v на одну и ту же область памяти.

Чтобы скопировать список, используйте vec = v[:]


Все это может показаться нелогичным. Почему бы не сделать копирование списка поведением по умолчанию? Рассмотрим ситуацию

def foo():
my_list = some_function()
# Do stuff with my_list

Разве вы не хотели бы my_list содержать точно такой же список, который был создан в some_function, и не заставлять компьютер тратить дополнительное время на создание копии. Для больших списков копирование данных может занять некоторое время. По этой причине Python не копирует список при назначении.



Разное Примечания:


  • Если вы знакомы с языками, использующими указатели. Внутренне, в результирующем языке ассемблера, vec и v - это просто указатели, которые ссылаются на адрес в памяти, с которого начинается список.



  • Другие языки смогли преодолеть препятствия, о которых я упоминал, благодаря использованию копирования при записи, которое позволяет объектам совместно использовать память до тех пор, пока они не будут изменены. К сожалению, в Python это никогда не реализовывалось.



  • О других способах копирования списка или выполнения глубокого копирования см. в разделе Список неожиданно изменяется после назначения. Почему это происходит и как я могу это предотвратить?



python