Я не могу понять, почему так происходит
abc = ['a', 'b', 'c']
c = abc
print(type(abc))
print(type(c))
for i in c:
if i == 'a' or i == 'b' or i == 'c':
c.remove(i)
i += 'y'
c.append(i)
print(c)
Я не могу понять почему при выводе выводит ['b', 'ay', 'cy'], а не ['ay', 'cy', 'by'] И у 'c' и у 'abc' тип list, но вывод расходится с результатом. Зато когда я пишу, что 'c' именно list(), то все отлично работает:
abc = ['a', 'b', 'c']
c = abc
print(type(abc))
print(type(c))
for i in list(c):
if i == 'a' or i == 'b' or i == 'c':
c.remove(i)
i += 'y'
c.append(i)
print(c)
Объясните пожалуйста как это работает.
Ответы (3 шт):
потому что сколько раз говорили - НЕ МЕНЯЙТЕ СПИСОК (УДАЛЯТЬ/ДОБАВЛЯТЬ элементы) КОГДА ДВИГАЕТЕСЬ ПО НЕМУ
вы ломаете логику работы for
когда же вы делаете
for i in list(c):
то ползаете по одному объекту (list(c)) - копии списка c, а меняете другой объект - сам список c
В первом примере происходит примерно следующее:
позиция в списке c - pos = 0, значение - a
удаляете этот элемент списка и у вас получается список ['b', 'c']
дальше добавляете к списку элемент ay и у вас получается список ['b', 'c', 'ay']
дальше переходите к следующему элементу в списке c - pos = 1, значение... c, потому что после удаления первого элемента списка все сдвинулось
в итоге удаляете элемент списка c и добавляете cy, получился список ['b', 'ay', 'cy']
цикл завершился, поскольку вы достигли конец первоначального списка
А вы добавьте отладочную печать:
...
for i in c:
print(i, c)
...
Вывод:
a ['a', 'b', 'c']
c ['b', 'c', 'ay']
cy ['b', 'ay', 'cy']
Видите? Список меняется на ходу, при этом у него перебираются элементы просто по номеру. Поэтому на второй итерации элемент b просто не перебирается - после remove он стал первым. Зато на третьей итерации в i будет cy, потому что он в этот момент на третьем месте.
Чинится это как обычно - итерацией по копии списка, вы делаете копию через list, но лучше делать копию явным образом:
for i in c.copy():
Вывод отладочной печати в этом случае:
a ['a', 'b', 'c']
b ['b', 'c', 'ay']
c ['c', 'ay', 'by']
Теперь всё как задумано.
Программа выполняется не так, как Вы хотите, потому что переменная i сначала удаляется, потом к ней прибавляется 'y' и она добавляется в конец списка. Чтобы код выполнялся правильно необходимо сделать так:
abc = ['a', 'b', 'c']
c = abc
print(type(abc))
print(type(c))
for i in range(len(c)):
if c[i] == 'a' or c[i] == 'b' or c[i] == 'c':
c[i] = c[i] + 'y'
print(c)
Теперь всё происходит так, как задумано. Во втором случае вы используете не сам список, а его копию, поэтому изменения происходящие в списке c, не отражаются в ней.
P S Иногда необходимо использовать визуализатор. Я, например, понял, что идёт не так только после работы с ним.