Изменение одного списка неожиданно приводит к изменению другого
У меня есть список формы
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?"