Junior — Senior
47
Особенности работы filter и одноразовых итераторов
Условие задачи
Разобрать, почему данная программа выводит именно такой результат и какие особенности поведения filter и итераторов приводят к этому.
seq = [1, 2, 3, 4, 5]
# Получаем итератор нечётных чисел из seq
odd_iter = filter(lambda x: x % 2, seq)
if any(odd_iter):
print("Has odds:")
for odd in odd_iter:
print(odd)
print(any(odd_iter))
Вывод программы:
Has odds:
3
5
False
Что происходит:
filterвозвращает итератор, а не список. Его элементы вычисляются «на лету» и могут быть получены только один раз.- В условии
if any(odd_iter):функцияanyпоследовательно перебирает элементы итератора, пока не встретит истинный (True). При этом первые два нечётных числа —1и3— проверяются, и как только найдено3(истинное значение), перебор останавливается. Итератор уже «прокручён» до элемента5. - После выполнения
anyитератор находится в состоянии «потраченной» части: уже прошедшие элементы недоступны. Поэтому в последующемfor odd in odd_iter:остаётся только один элемент —5, который и выводится. - Последний вызов
any(odd_iter)снова пытается пройтись по оставшимся элементам. Так как после вывода5в итераторе ничего не осталось,anyсразу возвращаетFalse.
Итого, filter создаёт одноразовый итератор, а любые функции, которые его потребляют (any, list, цикл for и т.п.), «истощают» его, делая последующие попытки получить данные пустыми.