Сообщить об ошибке.

Итератор как основа функционального стиля Python

Итераторы являются важной основой для написания программ в функциональном стиле.

Итератор в Python - это объект, представляющий поток данных, т.е. объект, который возвращает данные по одному элементу за раз. Итератор Python должен поддерживать метод с именем __next__(), который не принимает аргументов и всегда возвращает следующий элемент потока. Если в потоке больше нет элементов, то __next__() должен вызвать исключение StopIteration. Однако итераторы не обязательно должны быть конечными; вполне разумно написать итератор, генерирующий бесконечный поток данных.

Встроенная функция iter() принимает произвольный объект и пытается вернуть итератор, который вернёт содержимое или элементы объекта, поднимая TypeError, если объект не поддерживает итерацию. Некоторые из встроенных в Python типов данных поддерживают итерацию, наиболее распространенными из которых являются списки list и словари dict. Объект называется итерируемым, если для него можно получить итератор.

Можно поиграться с интерфейсом итератора вручную:

>>> L = [1, 2, 3]
>>> it = iter(L)
>>> it
# <...iterator object at ...>

# тоже самое что и next(it)
>>> it.__next__()
# 1
>>> next(it)
# 2
>>> next(it)
# 3
>>> next(it)
# Traceback (most recent call last):
#   File "<stdin>", line 1, in <module>
# StopIteration

Python ожидает итерируемые объекты в нескольких различных контекстах, наиболее важным из которых является цикл for/in. В конструкции for X in Y, Y должен быть итератором или некоторым объектом, для которого iter() может создать итератор.

Следующие два утверждения эквивалентны:

for i in iter(obj):
    print(i)

for i in obj:
    print(i)

Итераторы могут быть материализованы в виде списков или кортежей с помощью функций-конструкторов list() или tuple():

>>> L = [1, 2, 3]
>>> iterator = iter(L)
>>> t = tuple(iterator)
>>> t
# (1, 2, 3)

Распаковка последовательности также поддерживает итерацию: если наперед знать, что итератор вернёт N элементов, то можно распаковать их в кортеж из N переменных:

>>> L = [1, 2, 3]
>>> iterator = iter(L)
>>> a, b, c = iterator
>>> a, b, c
(1, 2, 3)

Встроенные функции, такие как max() и min(), могут принимать один аргумент - итератор и возвращать наибольший или наименьший элемент. Операторы in и not in также поддерживают итераторы: X in iterator истинно, если X найден в потоке, возвращенном итератором. Так же можно столкнутся с очевидными проблемами, если итератор бесконечен. Функции max(), min() и операторы in и not in никогда не вернут результат, если элемент X никогда не появится в потоке.

Обратите внимание, что по итератору можно двигаться только вперед. Нет возможности получить предыдущий элемент, сбросить итератор или сделать его копию!!! Объекты-итераторы могут дополнительно предоставлять эти дополнительные возможности, но протокол итератора определяет только метод __next__(). Следовательно, функция может потребить весь вывод итератора, и если нужно сделать что-то другое с тем же итератором, то придется создать его снова.