Пошаговое руководство по итераторам и генераторам в Python

Цикл while и цикл for должны активно использоваться в программировании на Python. Под капотом от нашего имени работает итератор. Сегодня вы изучите концепцию и использование итераторов и генераторов!

Итератор:

Итератор по определению предоставляет нам возможность перебирать некоторые контейнеры и скрывает конкретную логику итерации. Например, мы часто повторяем список, используя for , а также используем пересечение набора/карты. Существует некоторая разница в низкоуровневой реализации итерации массива и карты/набора. Однако итератор скрывает эти детали от программистов, и мы можем выполнять итерацию по желанию.

Чтобы реализовать итератор, вам необходимо предоставить реализацию функций __iter__() и __next__(). Вам нужно предоставить оба из них: если вы предоставите только __iter()__ , ваш объект будет итерируемым, но не будет итератором. Если вы предоставите только __next()__ , он не будет ни ни итерируемым, ни итератором. Не верите? Попробуйте функцию Python isinstance()!

В Python есть две внутренние функции, называемые iter() и next(). Вызов iter() вернет итератор объекта, реализованного __iter__() . next() возвращает следующий шаг итератора. Пример использования: my_iterator = iter(my_object), за которым следует next(my_iterator).. Когда возвращать нечего, next() вызовет исключение StopIteration, и итерация будет остановлена. Один интересный факт заключается в том, что если мы применяем функцию iter() несколько раз к объекту, например. iter(iter(my_obj)) равно iter(my_obj).

Узнав об этом, давайте напишем собственный итератор массива. В нашем случае нам нужно не только значение, но и индекс. Например, для списка [4,5,6] нам нужно, чтобы наш итератор печатал (0,4),(1,5),(2,6) соответственно. Что мы делаем? Итак, мы создаем класс, который реализует как __iter__(), так и __next__()!См. ниже:

Генератор:

Изучение итератора, вот родной брат итератора: генератор. Ну что такое генератор? Что ж, генератор проще и гибче в реализации, чем итератор, и он возвращает нам итератор для повторения. См. пример ниже:

Здесь мы определили генератор, и каждый раз, когда мы вызываем next(), он будет выводить следующее значение. По сути, генератор будет содержать алгоритм: пока мы знаем это значение в данный момент, мы можем правильно перейти к следующему значению. Обычно это делается с помощью ключевого слова yield. Используя yield, мы можем добиться этого. См. генератор Фибоначчи ниже:

Каждый раз функция будет останавливаться на части yield, а затем продолжит выполнение, начиная с последней остановки. Таким образом, общий рецепт создания генератора заключается в том, чтобы писать как обычно, но на каждом шаге, выдавая значение шага в этот момент. Как и в случае с нашим генератором Фибоначчи, каждый раз, когда мы продвигаемся вперед для вычисления следующего числа, мы получаем его значение.

Однако обычно мы не сочетаем использование next() и генератора вместе. Мы чувствуем себя более комфортно, просто бросив наш генератор в цикл for следующим образом:

Иногда, скажем, нам нужно 100 элементов потока из 100 миллионов чисел. Если мы попытаемся создать объект, который хранит все 100 миллионов чисел, он будет слишком массивным, как в случае с итератором. Однако, используя генератор, мы могли бы сделать это шаг за шагом и знаем, где правильно остановиться, без необходимости реализовывать функции __iter__() и __next()__.

В этом чтении мы представили концепцию и основное использование итератора и генератора Python. Теперь вы можете написать собственный итератор и генератор (например, создать итератор, выполняющий итерацию в обратном направлении для списка) и попробовать поиграть с ним! Этот инструмент станет удобным при реализации некоторых структур данных и алгоритмов, поскольку у вас есть полный контроль над тем, что искать в процессе итерации. Опять же, как обычно, удачного обучения и удачного кодирования!

Дополнительные материалы на PlainEnglish.io. Подпишитесь на нашу бесплатную еженедельную рассылку новостей. Подпишитесь на нас в Twitter и LinkedIn. Присоединяйтесь к нашему сообществу Discord.