Что такое генератор? Разница между генераторами и итераторами?

1. Итератор

  • Итератор — это объект, который позволяет проходить по последовательности (список, строка, кортеж) один элемент за раз.

  • Итератор реализует методы:

    • __iter__() — возвращает сам объект итератора

    • __next__() — возвращает следующий элемент, при достижении конца выдаёт StopIteration

Пример итератора

lst = [1, 2, 3]
it = iter(lst)

print(next(it))  # 1
print(next(it))  # 2
print(next(it))  # 3
# print(next(it))  # StopIteration

2. Генератор

  • Генератор — это специальный итератор, который создаёт элементы "на лету" при каждой итерации.

  • Экономит память, особенно для больших последовательностей.

  • Создаётся с помощью:

    1. Функций с yield

    2. Генераторных выражений ((...) вместо [...])

2.1 Функция-генератор

def my_gen(n):
    for i in range(n):
        yield i  # возвращает по одному элементу за раз

gen = my_gen(5)
for val in gen:
    print(val)

Вывод:

0
1
2
3
4

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

gen_exp = (x**2 for x in range(5))
print(next(gen_exp))  # 0
print(next(gen_exp))  # 1

3. Разница между генератором и обычным итератором

Характеристика
Итератор
Генератор

Создание

Через iter()

Функция с yield или (x for x in ...)

Память

Элементы хранятся полностью

Элементы создаются по мере запроса

Ключевой метод

__next__()

__next__() (реализован автоматически)

Использование

Любая последовательность

Большие последовательности, ленивые вычисления

Можно ли пересоздать

Да (создать новый итератор)

Нет, генератор один раз исчерпывается


4. Применение в автотестах

  • Обработка больших логов или API-данных без загрузки всего в память.

  • Генерация тестовых данных на лету:

def test_data(n):
    for i in range(n):
        yield {"username": f"user{i}", "password": "123"}
  • Используется в pytest с @pytest.mark.parametrize, когда много комбинаций данных.


💡 Вывод:

  • Генератор = ленивый итератор, экономит память.

  • Итератор = объект последовательности, по которому можно пройтись с next().


Отличия генераторов от генераторных выражений

В Python есть два похожих, но разных механизма:

  • Генераторы (generator functions) — это функции с yield, которые возвращают итератор.

  • Генераторные выражения (generator expressions) — это компактный синтаксис, похожий на list comprehension, но в круглых скобках.


1. Генераторы (generator functions)

Как создаются: Используем def и yield вместо return.

def my_gen():
    yield 1
    yield 2
    yield 3

g = my_gen()
print(next(g))  # 1
print(next(g))  # 2
print(next(g))  # 3

📌 Особенности:

  • yield приостанавливает выполнение функции и возвращает значение, но сохраняет состояние (переменные, позицию).

  • Можно содержать сложную логику, условия, вложенные циклы.

  • Можно использовать в нескольких местах yield, в отличие от return, который завершает выполнение.


2. Генераторные выражения (generator expressions)

Как создаются: Похожи на list comprehension, но с () вместо [].

g = (x**2 for x in range(5))

print(next(g))  # 0
print(next(g))  # 1
print(next(g))  # 4

📌 Особенности:

  • Это короткий синтаксис, когда логика простая.

  • Используются чаще для "одноразового" создания потока данных.

  • Нельзя написать сложный многострочный код (только одно выражение).


3. Отличия в таблице

Критерий
Генераторы (yield)
Генераторные выражения

Создание

Через def и yield

Через круглые скобки ()

Сложность логики

Можно писать сложные алгоритмы, условия

Только одно выражение

Читаемость

Более многословны

Короткие и компактные

Многострочность

Да

Нет

Где использовать

Когда логика сложная, есть много шагов

Когда нужно просто и быстро создать поток

Пример

def my_gen(): yield x

(x for x in range(10))


4. Общие черты

  • Оба ленивые — не создают весь список сразу, а выдают элементы по запросу.

  • Оба возвращают итератор.

  • Можно использовать в for, sum, max, list() и т. п.


5. Когда что использовать

  • Генератор (yield) — если нужно многострочное вычисление, сложные условия, несколько точек yield.

  • Генераторное выражение — если вычисление короткое и можно записать в одну строчку

Last updated

Was this helpful?