Генераторы

Модуль 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 лекция
Недоступен
Системные функции
Системные функции
Комментарии (19)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Mongoose Уровень 16
17 декабря 2025
Когда разрабатывали курс лекций по Phyton, появился ИИ, и разработчики решили, что обучающиеся будут сами доучиваться и додумывать, то что не понимают.
Андрей Уровень 25
21 октября 2025
Удивлялся по началу, почему в комментариях ругают материал и задачи. Но добравшись до этой темы, присоединяюсь ко всем рассерженным пользователям. Отвратительная халтура, что в материале, что в задачах, которая и повторяет один-в-один.
SWK Уровень 26
2 апреля 2025
Когда внезапно появляется конструкция

 received = yield
у студента наступает когнитивный диссонанс. Вы же ничего об этом не рассказали. Более того, вы рассказывали только вариант yield х. Зачем на одной странице выворачивать мозги ученикам? Почему нельзя сначала внятно перечислить все варианты?
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 Уровень 19
28 июля 2025
Самое смешное, что лекция тоже написана с помощью нейронки, просто автор её неумело пережевал
Laizis Уровень 32 Expert
22 февраля 2025
Качество задач оставляет желать лучшего
Николай Уровень 17
18 февраля 2025
Уделить сопрограммам и вложенным генераторам по 1 строчке текста? 🥺 Это мощно. И что то меня гложет сомнение, что генераторы имеют отношения к функциям высшего порядка (это так уровень называется)
Маруся Уровень 23
22 января 2025
Вопрос из теста: " Что такое лямбда-функция в Python?" Почему вариант "функция с неограниченным числом аргументов" - неправильный? В лекции написано, что аргументов может быть любое количество.
Japan_Dragon Уровень 32
3 февраля 2025
потому что есть более правильный ответ
SWK Уровень 26
2 апреля 2025
"Более правильный" - это как "более беременная"? Или как "осетрина второй свежести"?
Игорь Уровень 25
21 января 2025
Замыкание тяжеловато, конечно, пошло :/
5 сентября 2025
До сих пор думал, что одному мне стало тяжело с момента изучения замыканий..)
Сергей Уровень 25
28 декабря 2024
Нигде по тексту не написано что yield не только приостанавливает выполнение но и возращает значение переменной перед которой стоит так же как и return
Dmitry Ryabov Уровень 23
2 февраля 2025
Тоже смотрел на функции, описанные в примерах, и не мог понять каким образом они возвращают какое-то значение, ведь нигде нет return. Кстати вот тут неплохая статья про генераторы: ссылка
Marina Уровень 23 Expert
5 июля 2025
Спасибо за статью
Azat Rashitov Уровень 31
27 декабря 2024
Зачем в задачах использовать примеры из лекции? Можно же их немного поменять.