#python #list
Вопрос:
Я немного смущен тем, почему оба выхода меняются после восстановления, когда, конечно, это должен быть только один(выходные данные проиллюстрированы в примечаниях). Конечно, только первый должен измениться? Если бы кто-нибудь мог дать мне совет относительно того, почему это происходит, я был бы признателен
def switcher(y): # shifts two characters temp = y[0] y[0] = y[1] y[1] = temp sub = [[1,2,3],[1,2,3]] switcher(sub[0]) sub #[[2, 1, 3], [1, 2, 3]] #restore sub[0] = sub[1] sub # [[1, 2, 3], [1, 2, 3]] switcher(sub[0]) sub #[[2, 1, 3], [2, 1, 3]]
Комментарии:
1. В
python
вы можете поменять местами как:x, y = y, x
Ответ №1:
sub[0] = sub[1]
Вы определяете оба списка как один и тот же объект, поэтому последующее изменение применяется к ним обоим. Сделайте sub[0] = sub[1][:]
, например, чтобы создать копию (для списка есть еще несколько способов сделать это).
Ответ №2:
При этом вы sub[0] = sub[1]
присваиваете ссылку на значение индекса 1
, т. Е. [1, 2, 3]
в вашем случае на индекс 0, поэтому в конечном итоге оба списка находятся в одной и той же ячейке памяти, и изменение в любом из них приводит к соответствующему изменению в другом.
Вы можете проверить это с помощью id
встроенного модуля, который представляет ссылку на память для данного значения:
идентификаторы после инициализации:
gt;gt;gt; sub = [[1,2,3],[1,2,3]] gt;gt;gt; [id(s) for s in sub] [1385461417096, 1385461338824]
идентификаторы после вызова коммутатора:
gt;gt;gt; switcher(sub[0]) gt;gt;gt; [id(s) for s in sub] [1385461417096, 1385461338824]
идентификаторы после присвоения sub[0] = sub[1]
:
gt;gt;gt; sub[0] = sub[1] gt;gt;gt; [id(s) for s in sub] [1385461338824, 1385461338824]
Как вы можете видеть, идентификаторы одинаковы после назначения sub[0] = sub[1]
, оба вложенных списка изменяются при изменении одного из них
Ответ №3:
Оскорбительная строка — это назначение
sub[0] = sub[1]
Назначение никогда не копирует данные.
Вы говорите Python, что ссылки sub[0]
и sub[1]
теперь указывают на один и тот же объект списка в памяти (вместе с содержимым [1,2,3]
).
В вашем конкретном случае это легко исправить, взяв (неглубокую) копию списка справа от задания.
sub[0] = sub[1][:]
Ответ №4:
У вас проблемы со ссылками. Путем определения:
sub = [[1,2,3],[1,2,3]]
вы создаете список из двух разных списков, но когда вы это делаете:
sub[0] = sub[1]
вы говорите python скопировать sub[1] в sub[0], следовательно, для python ваш новый вектор будет:
sub lt;- [ reference_to_memory_where_sub1_is, sub1 ]
Чтобы избежать такого поведения, вы можете явно указать python дублировать объекты в памяти. Вы можете сделать это с помощью модуля «копировать».:
import copy def switcher(y): # shifts two characters temp = y[0] y[0] = y[1] y[1] = temp l1 = [1,2,3] l2 = [1,2,3] sub = [copy.deepcopy(l1),copy.deepcopy(l2)] switcher(sub[0]) print(sub) #[[2, 1, 3], [1, 2, 3]] #restore sub[0] = l1 print(sub) # [[1, 2, 3], [1, 2, 3]] switcher(sub[0]) print(sub) #[[2, 1, 3], [2, 1, 3]]