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

У меня есть список формы

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 изменить вообще?

5 ответов

Решение

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

VEC и V оба указатели. При кодировании vec = v вы назначаете v адрес для vec. Поэтому изменение данных в v также "изменит" vec.

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

vec = list(v)

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

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

from copy import deepcopy
vec = deepcopy(v)

или же

vec = v[:]

Запустите этот код, и вы поймете, почему меняется переменная 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. Надеюсь, это поможет!:)

Для экономии памяти vec будет указывать на тот же массив, если вы не укажете иначе.

скопировать массивы, как это vec=v[:]


Возможность указывать на массив вместо его копирования полезна при передаче данных от функции к функции. Если бы у вас была эта функция

def foo():
  return someBigArray

И вы хотели сделать что-то с SomeBigArray

def bar():
  arr = foo()
  processArray(arr)

Вам не нужно тратить время на ожидание, пока программа скопирует все данные в someBigArray в arr, поэтому вместо поведения по умолчанию указывается arr указатель на someBigArray.


Был задан похожий вопрос Как клонировать или скопировать список?

Вы могли бы использовать

vec=v[:] #but

"Мнение Алекса Мартелли (по крайней мере, в 2007 году) об этом заключается в том, что это странный синтаксис и не имеет смысла использовать его когда-либо.;) (По его мнению, следующий более читабелен)".

vec=list(v)

Я имею в виду, что это была ссылка Эреза... " Как клонировать или скопировать список в Python?"

Другие вопросы по тегам