Переменные постоянного назначения Python - PullRequest
0 голосов
/ 27 августа 2010

Я только что запустил python и наткнулся на что-то странное.

Следующий код назначает координату x = 1 и y = 2 для теста переменной.Переменная test2 присваивает себе то же значение, что и test, и затем значение [x] для test2 изменяется на старое значение [x] минус 1. Однако это работает нормально, но когда выполняется последняя часть, она не только минус 1из значения [x] в test2, он делает то же самое для значения [x] в тестовой переменнойПервый метод изменяет значение теста, а также значение test2.

test = [1,2];
test2 = test;
test2 = [test2[0] -1 ,test2[1]];

Может кто-нибудь объяснить, почему это происходит.

Спасибо TheLorax

Ответы [ 4 ]

4 голосов
/ 27 августа 2010

В Python, как и в Java, присваивание само по себе никогда не делает копию - как правило, присваивание добавляет еще одну ссылку к тому же объекту, что и правая часть =. (Передача аргумента работает так же). Странно, что вы никогда не слышали о концепции, когда Python довольно популярен, а Java еще более популярна (и многие другие языки имеют тенденцию работать аналогично, возможно, с большим количеством сложностей или отличий).

Когда вы хотите копию, вы запрашиваете копию (как часть выражения, которое находится справа, или используется для получения аргумента, который вы ' повторное прохождение)! В Python, в зависимости от ваших конкретных целей, есть несколько способов: популярный модуль copy стандартной библиотеки (с функциями copy для «мелких копий» и deepcopy - для «глубоких»). "копии, конечно, то есть те, где не только контейнер, но и каждый содержащийся элемент также рекурсивно копируется).

Часто, однако, вам нужен «новый список» - независимо от того, является ли исходная последовательность списком, копией или чем-то иным, что может повторяться, вам может быть все равно: вам нужен новый экземпляр list, чей предметы такие же, как у "чего-то другого". Идеальный способ выразить это - использовать list(somethingelse) - вызвать тип list, который всегда создает новый экземпляр списка, и дать ему в качестве аргумента итеративный элемент, элементы которого вы хотите в новом списке. Точно так же dict(somemapping) создает новый dict, а set(someiterable) создает новый набор - вызов типа для создания нового экземпляра этого типа является очень общей и полезной концепцией!

3 голосов
/ 27 августа 2010

Это потому, что когда вы делаете test2 = test, вы не копируете содержимое списка, а просто присваиваете test2 ссылку на исходный список. Таким образом, любые изменения в test2 также будут влиять на test.

Правильный способ сделать это - использовать deepcopy() из модуля копирования (или copy(), если вы можете избежать мелкой копии.

import copy
test2 = copy.deepcopy(test) # deep copy

test2 = copy.copy(test)) # shallow copy

test2 = test[:] # shallow copy using slices

См. на этой странице для более подробного объяснения, а также других способов копирования списка.

0 голосов
/ 27 августа 2010

Python не выполняет присваивания.

Это имя привязки.

Есть разница, и она чудесно и подробно объясняется здесь .

В вашем первом примере: Ваша первая строка связывает имя «test» с объектом списка, созданным выражением «[1,2]». Ваша вторая строка связывает имя «test2» с тем же объектом , который ограничен «test». Ваша третья строка изменяет объект, связанный с «test2», который совпадает с объектом, связанным с «test».

В вашем втором примере: Ваша первая строка связывает имя «test» с объектом списка, созданным выражением «[1,2]». Ваша вторая строка связывает имя «test2» с тем же объектом , который ограничен «test». Ваша третья строка связывает имя «test2» с новым объектом, созданным выражением «[test2 [0] -1, test2 1 ]".

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

>>> test = [1, 2]
>>> test2 = list(test)
>>> test2[0] = 3
>>> print(test)
[1, 2]
>>> print(test2)
[3, 2]

Обратите внимание, что это список с мелким копированием, поэтому изменение состояния объекта элемента в test2, конечно, повлияет на test, если тот же объект найден в этом списке.

p.s. Python. Полуприцепы колоны. Некрасиво. Ненужные. Не использовать.

0 голосов
/ 27 августа 2010

[1,2] - это массив, и когда вы присваиваете его test, вы назначаете ссылку на этот массив для тестирования. Поэтому, когда вы делаете test2=test, вы присваиваете ссылку на еще одну переменную. Внесите изменения в любую переменную, и массив будет изменен.

Ваш второй пример работает, потому что вы вообще создаете новый массив. С таким же успехом вы могли бы сделать это так:

test = [1,2]
test2 = [test[0]-1, test[1]]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...