Генераторы

Модуль 1: Python Core
8 уровень , 3 лекция
Открыта

4.1 Знакомство с генераторами

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

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

Генераторы на основе функций

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


def count_up_to(max):
    count = 1
    while count <= max:
        yield count
        count += 1
        
counter = count_up_to(5)
print(next(counter))  # Вывод: 1
print(next(counter))  # Вывод: 2
print(next(counter))  # Вывод: 3
print(next(counter))  # Вывод: 4
print(next(counter))  # Вывод: 5

Если в функции есть оператор yield, то Python вместо традиционного исполнения функции создает объект-генератор, который управляет состоянием выполнения функции.

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

Генераторные выражения похожи на списковые выражения (List Comprehension), но создаются с использованием круглых скобок вместо квадратных. Они также возвращают объект-генератор.


squares = (x ** 2 for x in range(10))

print(next(squares))  # Вывод: 0
print(next(squares))  # Вывод: 1
print(next(squares))  # Вывод: 4

Какой из способов вам больше нравится?

3.2 Преимущества генераторов

Эффективное использование памяти

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


def large_range(n):
    for i in range(n):
        yield i
        
for value in large_range(1000000):
    # Обрабатываем значения по одному
    print(value)

Ленивые вычисления

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


def fibonacci():
    a, b = 0, 1
    while True:
        yield a
        a, b = b, a + b
        
fib = fibonacci()
for _ in range(10):
    print(next(fib))

Удобство синтаксиса

Генераторы предоставляют удобный синтаксис для создания итераторов, что упрощает написание и чтение кода.

3.3 Использование генераторов

Примеры использования генераторов в стандартной библиотеке

Многие функции в стандартной библиотеке Python используют генераторы. Например, функция range() возвращает объект-генератор, который генерирует последовательность чисел.


for i in range(10):
    print(i)

Да, мир уже никогда не будет прежним.

Создание бесконечных последовательностей

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


def natural_numbers():
    n = 1
    while True:
        yield n
        n += 1
        
naturals = natural_numbers()
for _ in range(10):
    print(next(naturals))

Использование send() и close()

Объекты-генераторы поддерживают методы send() и close(), которые позволяют отправлять значения обратно в генератор и завершать его выполнение.


def echo():
    while True:
        received = yield
        print(received)
        
e = echo()
next(e)  # Запускаем генератор
e.send("Hello, world!")  # Вывод: Hello, world!
e.close()

3.4 Генераторы на практике

Генераторы и исключения

Генераторы могут обрабатывать исключения, что делает их мощным инструментом для написания более устойчивого кода.


def controlled_execution():
    try:
        yield "Start"
        yield "Working"
    except GeneratorExit:
        print("Generator closed")
        
gen = controlled_execution()
print(next(gen))  # Вывод: Start
print(next(gen))  # Вывод: Working
gen.close()  # Вывод: Generator closed

Работу с исключениями мы рассмотрим в следующих лекциях, но думаю вам будет полезно узнать, что генераторы отлично с ними работают.

Вложенные генераторы

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


def generator1():
    yield from range(3)
    yield from "ABC"
        
for value in generator1():
    print(value)

# Вывод
0
1
2
A
B
C

Объяснение:

yield from: Эта конструкция используется для делегирования части операций другому генератору, что позволяет упрощать код и улучшать читаемость.

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

Использование генераторов может значительно улучшить производительность программ за счет уменьшения использования памяти и более эффективного выполнения итераций.

Пример сравнения списков и генераторов


import time
import sys

def memory_usage(obj):
    return sys.getsizeof(obj)

n = 10_000_000

# Использование списка
start_time = time.time()
list_comp = [x ** 2 for x in range(n)]
list_time = time.time() - start_time
list_memory = memory_usage(list_comp)

# Использование генератора
start_time = time.time()
gen_comp = (x ** 2 for x in range(n))
gen_result = sum(gen_comp)  # Вычисляем сумму для сравнимости результатов
gen_time = time.time() - start_time
gen_memory = memory_usage(gen_comp)

print(f"Список:")
print(f"  Время: {list_time:.2f} сек")
print(f"  Память: {list_memory:,} байт")

print(f"\nГенератор:")
print(f"  Время: {gen_time:.2f} сек")
print(f"  Память: {gen_memory:,} байт")

Список:
  Время: 0.62 сек
  Память: 89,095,160 байт

Генератор:
  Время: 1.13 сек
  Память: 200 байт
2
Задача
Модуль 1: Python Core, 8 уровень, 3 лекция
Недоступна
Генератор Фибоначчи.
Генератор Фибоначчи.
2
Задача
Модуль 1: Python Core, 8 уровень, 3 лекция
Недоступна
Генератор выражений.
Генератор выражений.
1
Опрос
Системные функции, 8 уровень, 3 лекция
Недоступен
Системные функции
Системные функции
Комментарии (26)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Кэрривайт Уровень 25
18 мая 2026
Все это слишком сложно для меня, может я еще не готова.... Пойду на следующий уровень, может через попозже получится освоить генераторы и замыкаторы...... Час спустя... Генератор «замораживается» после выдачи каждой строки. Он не загружает весь файл сразу, а ждёт следующего запроса — это экономит память. Пример: генерация чисел Фибоначчи до бесконечности. Обычный цикл с return здесь невозможен — он либо зависнет, либо вернёт ограниченное количество значений. Спасибо, Алиса!
EvgenyXIV Уровень 31
31 марта 2026
В общий "хор" добавлю про сравнение производительности и памяти. В примере нет никакого сравнения, а просто вычисление параметров времени и памяти для неких разных кодов. Должна быть база для сравнения, т.е. одинаковый РЕЗУЛЬТАТ работы сравниваемых кодов. В примере такого результата нет - для списков РЕЗУЛЬТАТ это список квадратов, а для генератора РЕЗУЛЬТАТ это сумма квадратов.... Корректным сравнение станет, если расчёт суммы gen_total = sum(gen_comp) в коде с генератором заменить на построение списка квадратов gen_list = [value for value in gen_comp]: # Использование списка start_time = time.time() list_comp = [x ** 2 for x in range(n)] list_time = time.time() - start_time list_memory = memory_usage(list_comp) # Использование генератора start_time = time.time() gen_comp = (x ** 2 for x in range(n)) gen_list = [value for value in gen_comp] # Создание списка квадратов # gen_total = sum(gen_comp) # Вычисляем сумму для сравнимости результатов gen_time = time.time() - start_time gen_memory = memory_usage(gen_comp)
Anonymous #1 Уровень 1
20 февраля 2026
как заставить мозг даже не пытаться произносить слово yield
Кэрривайт Уровень 25
18 мая 2026
Иилд [jiːld]
MxWild Уровень 40
6 февраля 2026
Объяснение генераторов на курсе какое-то топорное. Вот нормальное объяснение и для чего это нужно: Генератор — это специальный тип функции, который позволяет итеративно получать последовательность значений без необходимости хранить все значения в памяти одновременно. Вместо return генераторы используют ключевое слово yield. Основная идея: Обычная функция: выполняется полностью и возвращает результат Генератор: приостанавливает выполнение после каждого yield и сохраняет состояние до следующего вызова
Анатолий Уровень 63
30 января 2026
Замыкания замкнули )))
Mongoose Уровень 25
17 декабря 2025
Когда разрабатывали курс лекций по Phyton, появился ИИ, и разработчики решили, что обучающиеся будут сами доучиваться и додумывать, то что не понимают.
Андрей Уровень 29
21 октября 2025
Удивлялся по началу, почему в комментариях ругают материал и задачи. Но добравшись до этой темы, присоединяюсь ко всем рассерженным пользователям. Отвратительная халтура, что в материале, что в задачах, которая и повторяет один-в-один.
SWK Уровень 26
2 апреля 2025
Когда внезапно появляется конструкция

 received = yield
у студента наступает когнитивный диссонанс. Вы же ничего об этом не рассказали. Более того, вы рассказывали только вариант yield х. Зачем на одной странице выворачивать мозги ученикам? Почему нельзя сначала внятно перечислить все варианты?
Александр Уровень 22
9 февраля 2026
что по поводу: received = yield some_value
Zlopyhatel Уровень 0
24 февраля 2025
Бесплатные уроки от нейросети, как надо объяснять: def echo(): while True: received = yield # Генератор ожидает значение print(received) # Печатает полученное значение e = echo() # Создаем экземпляр генератора next(e) # Запускаем генератор (до первой паузы на yield) e.send("Hello, world!") # Отправляем значение в генератор e.close() # Закрываем генератор Может ваши курсы не такие хорошие, как вы думаете?
SWK Уровень 26
2 апреля 2025
А, вдруг, они это осознаЮт?
Марина Уровень 14
7 апреля 2025
Спасибо, добрый человек!!!
shinobi Уровень 20
28 июля 2025
Самое смешное, что лекция тоже написана с помощью нейронки, просто автор её неумело пережевал
Laizis Уровень 32 Expert
22 февраля 2025
Качество задач оставляет желать лучшего