Найти - Пользователи
Полная версия: как устроен for или __iter__ ?
Начало » Python для новичков » как устроен for или __iter__ ?
1
soln
Приветствую.
Сразу скажу, что прежде чем сюда писать прочел соответствующую главу Бизли.
Ответа на мой вопрос, там не нашел.

Вобщем столкнулся я с непонятным для меня поведением for, а имено. Если преберать for(м) последовательность и при каждой итерации удалять из этого объекта возвращаемое значение.
То ощущение что фор бежит через 1
Я понимаю что, влюбом случае такие вещи нужно делать с копией объекта,
но всеже почему он так себя ведет?

In [87]: a = [1,2,3,4,5]
In [88]: [a.pop(a.index(x)) for x in a]
Out[88]: [1, 3, 5]
In [89]: a
Out[89]: [2, 4]
In [90]: a = [1,2,3,4,5]
In [91]: for x in a: print a.pop(a.index(x))
1
3
5
In [92]: a
Out[92]: [2, 4]
FishHook
Я Бизли не читал, попробую объяснить на пальцах.
Как Вы думаете, как внутри питона происходит перебор списка?
Я тоже не знаю как, но давайте предположим, что по индексу.
То есть вместо
for i in lst:
где-то там внутри делается такое
for (int i; i<len(lst); i++)
{
lst[i]
}
Ну то есть классический цикл. Что же происходит, если мы в процессе перебора удаляем элементы?
Мы говорим питону, перебирай от первого элемента до последнего, питон циклом извлекает элементы 1й, 2й, 3й, и тут казалось бы 4й, но! четвертый элемнт Вы удалили, и его место занял пятый! Питон об этом ничего не знает, он продолжает извлекать по индексу
Смотрите
1,2,3,4,5,6

мы удалили 4, какой элемент теперь будет пятым?
1,2,3,5,6
ШЕСТЬ
Ага, пятёрка вообще выпадает из перебора, потому что она была пятой, и цикл её показал бы на пятой 
иттерации, но она теперь стала четвертой и извлекается lst[4], но цикл то извлекает lst[5], а там у нас УЖЕ шестёрка
.

Не удаляйте элементы из списка в цикле. Никогда.


soln
FishHook
Ну то есть классический цикл. Что же происходит, если мы в процессе перебора удаляем элементы?
Мы говорим питону, перебирай от первого элемента до последнего, питон циклом извлекает элементы 1й, 2й, 3й, и тут казалось бы 4й, но! четвертый элемнт Вы удалили, и его место занял пятый! Питон об этом ничего не знает, он продолжает извлекать по индексу
Смотрите
1,2,3,4,5,6
Да наверно Вы правы.
и это как раз объесняет по чему проход получается через один.
в случае
[a.pop(a.index(x)) for x in a]
FishHook
Не удаляйте элементы из списка в цикле. Никогда.

Это поняно. Если надо изменить список в цикле пользуюсь либо поверхносной копией либо copy.deepcopy
FishHook
soln
Это поняно. Если надо изменить список в цикле пользуюсь либо поверхносной копией либо copy.deepcopy
Да проще всё! Вместо того, чтобы удалять элементы, вы их просто не добавляйте. То есть мы делаем перебор по коллекции, и все элементы добавляем в другую коллекцию кроме тех, которые у нас “плохие”.
a = [1, 2, 3, 4]
a = filter(lambda x: x%2, a)
ну или фором или списковым выражением, как угодно, смысл в том, что сначала копировать, а потом фильтровать - глупо. Объедините фильтрацию и копирование в одну операцию.
soln
FishHook
Вместо того, чтобы удалять элементы, вы их просто не добавляйте. То есть мы делаем перебор по коллекции, и все элементы добавляем в другую коллекцию кроме тех, которые у нас “плохие”.
Хм. Аведь и вправду. Спасибо.
pyuser
FishHook
Не удаляйте элементы из списка в цикле. Никогда.
Да можно удалять элементы вцикле, нет в этом ничего ужасного, просто двигаться по списку нужно от конца к началу.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB