Найти в Дзене
Self Study

Итераторы и генераторы в Python

Итератор Итератор - это объект, который поддерживает протокол итератора, то есть имеет методы iter() и next(). Метод iter() возвращает сам итератор, а метод next() возвращает следующее значение из последовательности или вызывает исключение StopIteration, если значения закончились. Итератор можно использовать в цикле for или с функцией next(). Примеры контейнеров, которые поддерживают протокол итератора: списки (list), строки (str), словари (dict), множества (set), файлы (file) и другие. Пример класса, который реализует протокол итератора с методами iter() и next(): Генератор Генератор - это функция, которая использует ключевое слово yield для возврата значений из последовательности. Когда функция-генератор вызывается, она не выполняется сразу, а возвращает объект-генератор, который также является итератором. Когда метод next() объекта-генератора вызывается, функция-генератор продолжает выполнение до следующего оператора yield и возвращает значение после него. Когда функция-генератор за
Оглавление

Итератор

Итератор - это объект, который поддерживает протокол итератора, то есть имеет методы iter() и next(). Метод iter() возвращает сам итератор, а метод next() возвращает следующее значение из последовательности или вызывает исключение StopIteration, если значения закончились. Итератор можно использовать в цикле for или с функцией next().

Примеры контейнеров, которые поддерживают протокол итератора: списки (list), строки (str), словари (dict), множества (set), файлы (file) и другие.

Пример класса, который реализует протокол итератора с методами iter() и next():

Реализация последовательности Фибоначчи через итераторы
Реализация последовательности Фибоначчи через итераторы

Генератор

Генератор - это функция, которая использует ключевое слово yield для возврата значений из последовательности. Когда функция-генератор вызывается, она не выполняется сразу, а возвращает объект-генератор, который также является итератором. Когда метод next() объекта-генератора вызывается, функция-генератор продолжает выполнение до следующего оператора yield и возвращает значение после него. Когда функция-генератор завершается или достигает return, она вызывает исключение StopIteration.

Для создания и использования генераторов в Python с помощью функций с ключевым словом yield нужно выполнить следующие шаги:

  • Определить функцию-генератор, которая использует оператор yield для возврата значений из последовательности по одному за раз. Функция может содержать несколько операторов yield или циклы с yield.
  • Вызвать функцию-генератор для получения объекта-генератора, который также является объектом-итератором.
  • Вызывать функцию next() на объекте-генераторе для получения следующего значения из последовательности или обработать исключение StopIteration.

Пример функции-генератора, которая возвращает бесконечную последовательность чисел:

Функция генератор, генерирующая бесконечную последовательность
Функция генератор, генерирующая бесконечную последовательность

Различия между итераторами и генераторами

  • Итераторы создаются с помощью классов или функций iter() и next(), а генераторы создаются с помощью функций с yield
  • Итераторы обычно реализуют конкретную логику перебора элементов контейнера или диапазона значений, а генераторы обычно реализуют ленивые вычисления на основе некоторого алгоритма
  • Итераторы могут быть перезапущены с помощью метода iter(), а генераторы нельзя перезапустить после того, как они завершились

Генераторное выражение

Генераторное выражение - это более короткий способ создания объекта-генератора. Оно похоже на списковое включение, но вместо создания списка, создает объект-генератор, по которому можно итерироваться для получения значений из генератора.

Синтаксис генераторного выражения:

(<выражение> for <переменная> in <итерируемый объект> if <условие>)

Пример генераторного выражения, которое фильтрует элементы из списка по определенному условию:

numbers = [1, 2, 3, 4, 5]
# Генераторное выражение для получения четных чисел из списка even_numbers = (n for n in numbers if n % 2 == 0)
# Выводим значения из генератора с помощью функции next() print(next(even_numbers)) # 2
print(next(even_numbers)) # 4

Асинхронные итераторы и генераторы

Итераторы и генераторы имеют свои асинхронные аналоги. Асинхронные итераторы и генераторы - это специальные виды итераторов и генераторов, которые позволяют выполнять асинхронный код внутри цикла for. Они отличаются от своих синхронных версий тем, что используют ключевые слова async и await для определения и вызова асинхронных функций.

Асинхронные итераторы и генераторы применяются в ситуациях, когда нужно обрабатывать потоки данных, которые приходят нерегулярно или с задержками. Например, можно использовать асинхронный генератор для чтения данных из веб-сокета или из базы данных.

Пример асинхронного генератора, который возвращает случайные числа с разными интервалами:

Реализация асинхронного генератора, возвращающего случайные числа
Реализация асинхронного генератора, возвращающего случайные числа

Заключение

Вот краткий итог основных различий между итераторами и генераторами в Python:

  • Итераторы - это объекты, имеющие методы __iter__ и __next__, которые позволяют получить следующий элемент из последовательности. Генераторы - это специальные виды итераторов, которые создаются с помощью функций с ключевым словом yield. При использовании yild, выполнение функции приостанавливается и возвращается текущее значение.
  • Итераторы обычно реализуются с помощью классов, а генераторы - с помощью функций. Итераторы используют ключевое слово return для возврата значения, а генераторы - ключевое слово yield.
  • Итераторы не используют никаких переменных для итерации, а генераторы используют локальные переменные и сохраняют состояние этих переменных при каждом вызове yield.

Преимущества использования генераторов для экономии памяти и упрощения кода:

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