Какое ключевое слово создает генератор в Python?

Ответ

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

Пример простого генератора:

def countdown(n):
    """Генератор, который отсчитывает от n до 1."""
    while n > 0:
        yield n
        n -= 1

# Использование
for number in countdown(5):
    print(number)  # Выведет: 5, 4, 3, 2, 1

Почему это полезно:

  • Экономия памяти: Генератор не хранит всю последовательность в памяти, а вычисляет каждое значение на лету. Это критично для работы с большими или бесконечными потоками данных.
  • Ленивые вычисления: Код внутри функции выполняется только при обращении к следующему элементу (например, в цикле for или при вызове next()).

Выражение-генератор (generator expression) — это более компактная форма, похожая на list comprehension:

# List comprehension (создает список в памяти)
squares_list = [x**2 for x in range(1000000)]

# Generator expression (ленивое вычисление)
squares_gen = (x**2 for x in range(1000000))

print(next(squares_gen))  # 0
print(next(squares_gen))  # 1

Ответ 18+ 🔞

А, генераторы! Ну это же, ёпта, одна из самых хитрожопых и полезных штук в питоне. Смотри, чтобы не охуеть от их простоты.

Вот представь: обычная функция — это как бутылка водки. Открыл, выпил — всё, пусто, пиздец. А генератор — это как волшебный графин, из которого можно наливать по стопке, когда захочешь, и он никогда не кончается, пока ты не скажешь «стоп». Магия, блядь.

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

Вот тебе простейший пример, чтоб мозг не взорвался:

def countdown(n):
    """Генератор, который отсчитывает от n до 1."""
    while n > 0:
        yield n
        n -= 1

# Использование
for number in countdown(5):
    print(number)  # Выведет: 5, 4, 3, 2, 1

Видишь? Он не вываливает тебе сразу список [5,4,3,2,1] в память. Он лениво, по-царски, выдаёт цифры по одной, когда ты в цикле просишь. Пока не дойдёт до нуля и не накроется медным тазом.

А теперь, блядь, главный вопрос: нахуя это надо?

  • Памяти не жрёт, как свинья. Представь, тебе нужно пройтись по миллиону записей. Генератор не будет держать в памяти этот овердохуища список, он будет выдавать элементы по одному, как конвейер. Экономия — мать ебушки-воробушки.
  • Ленивые вычисления. Код внутри выполняется только тогда, когда ты говоришь «давай, сука, следующий!» (через next() или в цикле). Пока не попросил — он спит и не парится. Умно, как мартышлюшка с бананом.

Есть ещё более короткая форма — выражение-генератор. Это как list comprehension, только для бедных и умных. Смотри, не перепутай:

# List comprehension (тупой и жадный: создаёт весь список сразу и грузит память)
squares_list = [x**2 for x in range(1000000)]  # Пиздец твоей оперативке!

# Generator expression (хитрый и ленивый: просто обещает посчитать, когда попросят)
squares_gen = (x**2 for x in range(1000000))   # Вот это уже красота!

print(next(squares_gen))  # 0 - на, получи, распишись
print(next(squares_gen))  # 1 - на, ещё одну

Круглые скобочки вместо квадратных — и вуаля, у тебя не список, а генератор. Всё гениальное просто, ёпта. Главное — понять эту идею лени, а потом сам от себя офигеешь, как раньше без этого жил.