В чем разница между итератором, генератором и корутиной в Python

Ответ

Это связанные, но разные концепции в Python, которые служат для последовательной обработки данных и асинхронного программирования.

1. Итератор (Iterator)

Это объект, представляющий поток данных. Он реализует протокол итератора, который состоит из двух методов:

  • __iter__(): Возвращает сам объект-итератор.
  • __next__(): Возвращает следующий элемент из последовательности. Когда элементы заканчиваются, вызывает исключение StopIteration.

Любой объект, который можно перебрать в цикле for, является итерируемым (iterable), а сам цикл неявно создает из него итератор.

Пример (класс-итератор):

class Counter:
    def __init__(self, limit):
        self.limit = limit
        self.current = 0

    def __iter__(self):
        return self

    def __next__(self):
        if self.current < self.limit:
            self.current += 1
            return self.current
        else:
            raise StopIteration

# Использование
for num in Counter(3):
    print(num) # 1, 2, 3

2. Генератор (Generator)

Это простой способ создания итераторов. Генератор — это функция, которая использует ключевое слово yield для возврата значений. При каждом вызове yield выполнение функции приостанавливается, а ее состояние сохраняется. Это позволяет создавать "ленивые" последовательности, которые генерируют значения на лету и не хранят их все в памяти.

Пример (функция-генератор):

def counter_generator(limit):
    current = 0
    while current < limit:
        current += 1
        yield current

# Использование
for num in counter_generator(3):
    print(num) # 1, 2, 3

Ключевая идея: Все генераторы являются итераторами, но не наоборот.

3. Корутина (Coroutine)

Корутина (или сопрограмма) — это обобщение концепции генератора, предназначенное для кооперативной многозадачности. В современном Python корутины объявляются с помощью async def.

Они могут приостанавливать свое выполнение в точках await, отдавая управление циклу событий (event loop), который может запустить другую задачу. Это основа асинхронного программирования в asyncio.

Пример (корутина):

import asyncio

async def my_coroutine():
    print("Начало выполнения корутины")
    # Приостанавливаем выполнение на 1 секунду, 
    # отдавая управление другим задачам
    await asyncio.sleep(1)
    print("Корутина возобновила работу и завершается")

asyncio.run(my_coroutine())

Итог:

  • Итератор: Базовый объект для пошагового перебора.
  • Генератор: Удобная "фабрика" итераторов с помощью yield.
  • Корутина: "Прокачанный" генератор (async/await) для асинхронных операций.