Функция изменяет оба списка вместо одного списка на основе «0» в Python

#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]]