Итераторы и генераторы Python3
Iterator
Итерация — одна из самых мощных возможностей Python и способ доступа к элементам коллекции.
Итератор — это объект, который может запоминать позицию обхода.
Объект-итератор начинает обход с первого элемента коллекции, пока не будут перебраны все элементы. Итераторы могут двигаться только вперёд, а не назад.
У итераторов есть два основных метода:iter()иnext()。
Строки, списки или объекты-кортежи можно использовать для создания итераторов:
Пример (Python 3.0+)
>>> it = iter(list) # Создать объект итератора
>>> print (next(it)) # Вывести следующий элемент итератора
1
>>> print (next(it))
2
>>>
Объекты-итераторы можно перебирать с помощью обычного оператора for:
Пример (Python 3.0+)
Выполнение вышеуказанной программы дает следующий вывод:
1 2 3 4
Вы также можете использовать функцию next():
Пример (Python 3.0+)
Выполнение вышеуказанной программы дает следующий вывод:
1 2 3 4
Создание итератора
Чтобы использовать класс в качестве итератора, необходимо реализовать в классе два метода: __iter__() и __next__().
Если вы уже понимаете объектно-ориентированное программирование, вы знаете, что у классов есть конструктор. Конструктор Python — это __init__(), который выполняется при инициализации объекта.
Для получения дополнительной информации см.:Объектно-ориентированное программирование в Python 3
Метод __iter__() возвращает специальный объект-итератор, который реализует метод __next__() и сигнализирует о завершении итерации через исключение StopIteration.
Метод __next__() (next() в Python 2) возвращает следующий объект итератора.
Создайте итератор, который возвращает числа, начиная с начального значения 1 и увеличивая на 1 на каждом шаге:
Пример (Python 3.0+)
Вывод после выполнения:
1 2 3 4 5
StopIteration
Исключение StopIteration используется для сигнализации о завершении итерации и предотвращения бесконечных циклов. В методе __next__() мы можем настроить его так, чтобы после выполнения заданного числа циклов вызывалось исключение StopIteration для завершения итерации.
Остановить выполнение после 20 итераций:
Пример (Python 3.0+)
Вывод после выполнения:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
Генератор
В Python функции, использующие `yield`yield, называются генераторами (generator).
yield`yield` — это ключевое слово, используемое для определения функций-генераторов. Функция-генератор — это особый вид функции, которая может выдавать значения шаг за шагом во время итерации, вместо того чтобы возвращать все результаты сразу.
В отличие от обычных функций, генератор — это функция, которая возвращает итератор и может использоваться только для операций итерации. Проще говоря, генератор — это итератор.
Когда в функции-генераторе используется `yield`yield-инструкция, выполнение функции приостанавливается, иyieldвыражение после `yield` возвращается как значение текущей итерации.
Затем каждый раз, когда вызывается метод генератораnext()`__next__()` или для итерации используется циклfor`for`, функция возобновляет выполнение с того места, где она была приостановлена в последний раз, пока не встретит очереднойyield`yield`-инструкция. Таким образом, функция-генератор может выдавать значения шаг за шагом, без необходимости вычислять и возвращать все результаты сразу.
Вызов функции-генератора возвращает объект-итератор.
Ниже приведён простой пример, демонстрирующий использование функций-генераторов:
Пример
В приведённом выше примереcountdown— это функция-генератор. Она использует инструкции yield, чтобы постепенно выдавать числа countdown от n до 1. Каждый раз, когда выполняется инструкция yield, функция возвращает текущее значение countdown и при следующем вызове продолжает выполнение с того места, где была последняя пауза.
Создавая объект-генератор и используя функцию next() или цикл for для перебора генератора, мы можем постепенно получать значения, которые выдаёт функция-генератор. В этом примере мы сначала используем функцию next(), чтобы получить первые три значения countdown, затем используем цикл for, чтобы получить оставшиеся два.
Преимущество функций-генераторов в том, что они могут выдавать значения по запросу, избегая одновременного создания большого объёма данных и занятия большого объёма памяти. Кроме того, генераторы могут без проблем работать с другими инструментами итерации (например, с циклами for), обеспечивая краткий и эффективный способ итерации.
Выполнение вышеуказанной программы дает следующий вывод:
5 4 3 2 1
В следующем примере используется yield для реализации последовательности Фибоначчи:
Пример (Python 3.0+)
Выполнение вышеуказанной программы дает следующий вывод:
0 1 1 2 3 5 8 13 21 34 55Другие расширения