Подтвердить что ты не робот

Переменное назначение и модификация (в python)

Когда я запускал этот script (Python v2.6):

a = [1,2]
b = a
a.append(3)
print a
>>>> [1,2,3]
print b
>>>> [1,2,3]

Я ожидал print b для вывода [1,2]. Почему b изменился, когда все, что я сделал, изменилось? Является ли b постоянно привязанным к? Если да, могу ли я сделать их независимыми? Как?

4b9b3361

Ответ 1

Управление памятью в Python включает в себя локальную ячейку памяти кучи, содержащую все объекты и структуры данных Python.

Время выполнения Python работает только с ссылками на объекты (все они живут в куче): то, что происходит на стеке Python, всегда ссылается на ценности, которые живут где-то в другом месте.

>>> a = [1, 2]

python variables

>>> b = a

python variables

>>> a.append(3)

python variables

Здесь мы можем ясно видеть, что переменная b связана с тем же объектом, что и a.

Вы можете использовать оператор is для проверки, если два объекта физически одинаковы, это означает, что они имеют одинаковый адрес в памяти. Это также можно проверить также с помощью функции id().

>>> a is b
>>> True
>>> id(a) == id(b)
>>> True

Итак, в этом случае вы должны явно запросить копию. Как только вы это сделаете, больше не будет связи между двумя отдельными объектами списка.

>>> b = list(a)
>>> a is b
>>> False

python variables

Ответ 2

Объекты в Python хранятся по ссылке: вы не назначаете значение a на b, а указатель на объект, на который указывает a.

Чтобы эмулировать присвоение по значению, вы можете сделать копию следующим образом:

import copy

b = copy.copy(a)

# now the code works as "expected"

Помните, что это имеет недостатки производительности.

В случае массива существует специальный метод, который использует срезы:

b = a[:]

# code also works as expected here

Обновление. В дополнение к этому, с некоторыми объектами вы можете использовать конструктор - это включает в себя списки:

b = list(a)

Ответ 3

Короткий ответ - указатели.

При вводе b = a устанавливается b на тот же массив, на который смотрит a. Вы должны создать новый массив с копиями элементов для их разделения. В этом случае что-то вроде b = [n for n in a] будет работать нормально. Для более сложных операций вы можете проверить http://docs.python.org/library/copy.html.

Ответ 4

Возможно, вы захотите посмотреть эту ссылку. Проблема, с которой вы здесь столкнулись, - это a и b, указывающие на одну и ту же ячейку памяти, поэтому ее изменение меняет другую. Вместо этого вы хотите сделать что-то вроде этого:

a = [1,2]
b = list(a)

Ответ 5

a является указателем на список [1,2].

Когда вы выполняете назначение b = a, значение b является адресом списка [1,2].

Итак, когда вы делаете a.append(3), вы фактически не меняете a, вы меняете список, на который указывает a. Поскольку a и b оба указывают на один и тот же список, оба они изменяются при изменении другого.

Ответ 6

Если вы просто хотите скопировать содержимое списка a в b, вместо того чтобы сделать b указателем на:

b = a[:]

Использование оператора slice скопирует содержимое списка в b, чтобы вы, например, стали:

a = [1,2]
b = a[:]
a.append(3)
print a
>>>> [1,2,3]
print b
>>>> [1,2]