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

19 июня 2026
Автор

Антон Ларичев

Введение

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

В этой статье мы разберём, как работают генераторы, что делает ключевое слово yield, и в каких ситуациях генераторы незаменимы.

Что такое генератор

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

def simple_generator():
    yield 1
    yield 2
    yield 3

# Создаём объект генератора
gen = simple_generator()

# Получаем значения по одному
print(next(gen))  # 1
print(next(gen))  # 2
print(next(gen))  # 3

При вызове генераторной функции код внутри неё не выполняется сразу. Вместо этого Python возвращает объект генератора. Код выполняется только при запросе следующего значения через next() или цикл for.

Как работает yield

Ключевое слово yield работает как return, но с важным отличием: оно не завершает функцию, а приостанавливает её выполнение, сохраняя текущее состояние. При следующем вызове next() выполнение продолжается ровно с того места, где остановилось.

def countdown(n):
    print("Начинаем обратный отсчёт")
    while n > 0:
        yield n
        n -= 1
    print("Готово!")

# Создаём генератор
counter = countdown(3)

print(next(counter))
# Выведет: Начинаем обратный отсчёт
# Выведет: 3

print(next(counter))
# Выведет: 2

print(next(counter))
# Выведет: 1

# При следующем вызове next() выведет "Готово!" и выбросит StopIteration

Обратите внимание: строка «Начинаем обратный отсчёт» выводится только при первом вызове next(), а не при создании генератора.

Генераторы и циклы for

Чаще всего генераторы используются в цикле for, который автоматически вызывает next() и обрабатывает исключение StopIteration:

def fibonacci(limit):
    """Генератор чисел Фибоначчи до заданного предела"""
    a, b = 0, 1
    while a < limit:
        yield a
        a, b = b, a + b

# Перебираем числа Фибоначчи до 100
for num in fibonacci(100):
    print(num, end=" ")
# Выведет: 0 1 1 2 3 5 8 13 21 34 55 89

Экономия памяти

Главное преимущество генераторов — ленивые вычисления. Значения создаются по запросу, а не хранятся в памяти все сразу. Сравним список и генератор:

import sys

# Список — хранит все элементы в памяти
numbers_list = [x ** 2 for x in range(1000000)]
print(sys.getsizeof(numbers_list))  # ~8 МБ

# Генератор — хранит только текущее состояние
numbers_gen = (x ** 2 for x in range(1000000))
print(sys.getsizeof(numbers_gen))   # ~200 байт

Разница огромна: список занимает мегабайты, а генератор — всего несколько сотен байт, независимо от количества элементов.

Если вы хотите детальнее изучить Python и его продвинутые возможности — приходите на наш большой курс Python-разработчик с нуля. На курсе 180 уроков и 80 упражнений, AI-тренажёры для практики 24/7, решение задач с живым ревью наставника, еженедельные встречи с менторами.

Генератор для чтения больших файлов

Один из классических сценариев применения генераторов — построчное чтение больших файлов:

def read_large_file(filepath):
    """Читает файл построчно, не загружая его целиком в память"""
    with open(filepath, 'r', encoding='utf-8') as f:
        for line in f:
            yield line.strip()

# Обрабатываем файл любого размера
for line in read_large_file('huge_log.txt'):
    if 'ERROR' in line:
        print(line)

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

Цепочки генераторов

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

def read_lines(filepath):
    """Читает строки из файла"""
    with open(filepath, 'r') as f:
        for line in f:
            yield line.strip()

def filter_nonempty(lines):
    """Пропускает пустые строки"""
    for line in lines:
        if line:
            yield line

def to_uppercase(lines):
    """Преобразует строки в верхний регистр"""
    for line in lines:
        yield line.upper()

# Конвейер обработки
pipeline = to_uppercase(filter_nonempty(read_lines('data.txt')))
for line in pipeline:
    print(line)

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

yield from — делегирование генераторов

Начиная с Python 3.3 можно использовать конструкцию yield from для делегирования работы другому генератору или итерируемому объекту:

def gen_numbers():
    yield from range(3)       # 0, 1, 2
    yield from range(10, 13)  # 10, 11, 12

for n in gen_numbers():
    print(n, end=" ")
# Выведет: 0 1 2 10 11 12

yield from особенно полезен для рекурсивных генераторов:

def flatten(nested):
    """Рекурсивно разворачивает вложенные списки"""
    for item in nested:
        if isinstance(item, list):
            yield from flatten(item)
        else:
            yield item

data = [1, [2, 3], [4, [5, 6]], 7]
print(list(flatten(data)))
# Выведет: [1, 2, 3, 4, 5, 6, 7]

Частые ошибки

  • Повторное использование генератора. Генератор можно обойти только один раз. После исчерпания он не «перезаряжается» — нужно создавать новый объект.
  • Вызов next() без обработки StopIteration. Когда генератор исчерпан, next() выбросит исключение. Используйте next(gen, default) для безопасного извлечения.
  • Попытка узнать длину генератора через len(). Генераторы не поддерживают len(), так как количество элементов заранее неизвестно.

Частозадаваемые вопросы

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

Когда стоит использовать генератор вместо списка? Используйте генераторы, когда работаете с большими объёмами данных, читаете файлы построчно, обрабатываете потоки или создаёте бесконечные последовательности. Если данных немного и нужен произвольный доступ по индексу — используйте список.

Можно ли преобразовать генератор в список? Да, с помощью list(generator). Но это загрузит все элементы в память, что может нивелировать преимущество генератора.

Заключение

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

Для закрепления навыков работы с генераторами и другими продвинутыми возможностями Python рекомендуем курс Python-разработчик с нуля. В первых 3 модулях курса доступно бесплатное содержание, что позволяет освоить основы языка и понять структуру курса до покупки полного доступа.

Стрелочка влевоГенераторные выражения в Python — синтаксис и примерыФункции в Python и способы их вызоваСтрелочка вправо

Постройте личный план изучения Python до уровня Middle — бесплатно!

Python — часть карты развития Backend

  • step100+ шагов развития
  • lessons30 бесплатных лекций
  • lessons300 бонусных рублей на счет

Все гайды по Python

Как отправлять запросы с помощью requests в PythonПочему Python выводит значение без команды printКак работает команда print в PythonВозможности Python для автоматизации задачРабота с JSON в Python на примерахPython get — методы получения данныхКак находить и исправлять ошибки в PythonРабота с данными через API и внешние сервисыСтруктура и оформление кода PythonОсновы Django с PythonПолезные приёмы в Python для повседневной работыИспользование locals в Python для отладкиИнтеграция PHP и PythonКак выполнять HTTPS-запросы в PythonFastAPI Python — быстрый старт: создание REST API с нуляКак работать с API в Python
Ввод целого числа в PythonВедение логов в PythonУдаление данных в Python с помощью removeОбработка исключений с помощью try/except в PythonФункция super() в Python — как вызвать метод родителяСоздание собственных контекстных менеджеров в PythonРабота с символами программирования PythonРабота с переменной X в PythonРабота с классами в PythonКак скачать Python на компьютерПростая программа на Python для начинающихОсновы Python для тех, кто начинаетЧто нового в Python 3Поддерживается ли Python 2 и стоит ли его использоватьPython 1 — с чего начиналась история языкаКоманда python print - полное руководство по выводу данныхПравила именования переменных в PythonПользовательские исключения в PythonОсновы Python coreОписание объектов PythonНаследование классов в Python — основы и примерыМножественное наследование в Python — примеры и MROКонтекстный менеджер with в Python — как работает и зачем нуженКомментарии в Python — однострочные, многострочные и docstringКакой Python выбрать для установкиКак вывести целое число с помощью print в PythonКак установить Python на Windows macOS и LinuxКак пользоваться консолью PythonКак получить последний элемент в PythonКак найти значение в PythonКак настроить PythonКак использовать print для строк в PythonКак работает интерпретатор PythonИнструкция по работе с PythonБлок finally в обработке исключений PythonЦелые числа в PythonАбстрактные классы в Python — ABC и abstractmethod
Загрузка данных PythonУправление проектами на GitHub с PythonСоздание веб-приложений на Flask PythonСоздание бота на PythonСоздание интерфейсов Python QTСоздание игр с PygameСоздание GUI в PythonКак работать со словарями в PythonРабота с библиотеками через Python PackagingРабота со временем в Python при помощи модуля timePython name — особенности переменнойМатематические операции в Python с модулем mathPython listing — что это и как использоватьPytest — тестирование на Python: полное руководствоОбработка изображений с OpenCV PythonNumPy в Python — основы и применение в задачахМашинное обучение с PythonИспользование Anaconda с PythonМодуль contextlib в Python — утилиты для контекстных менеджеровБиблиотеки Python и их применение в проектах
Возврат значений из функции в PythonВложенные функции в PythonСоздание собственных декораторов в PythonРабота с функцией map в PythonЦикл while в Python и примеры использованияОбработка чисел, введённых через input в PythonОсновные операторы в Python с примерамиУсловные выражения if else в Python для начинающихКак выполняется вызов функций call в PythonПродвинутые генераторы в Python — send, throw, close и корутиныПозиционные и именованные аргументы в PythonОбъявление переменных и управление областью видимости в PythonПередача аргументов по ссылке и по значению в PythonОсновные методы Python и примеры их использованияПередача аргументов через args и kwargs в PythonОператор match/case в Python 3.10+ — основы структурного сопоставленияПаттерны match/case в Python — деструктуризация, guard и вложенные шаблоныПрактические примеры match/case в Python — реальные сценарии примененияЛокальные и глобальные переменные в PythonЧасто используемые команды PythonКлючевые слова global и nonlocal в PythonКак создавать функции в PythonКак работает сборщик мусора в PythonКак работает область видимости переменных в PythonКак работает функция callable в PythonКак работает функция any и all в PythonКак проверить тип переменной в PythonКак передать функцию как аргумент в PythonКак использовать функцию isinstance в PythonКак использовать функцию filter в PythonКак использовать функцию filter в PythonКак использовать функцию eval безопасно в PythonКак использовать декораторы в PythonИзменяемые и неизменяемые типы данных в PythonГенераторные выражения в Python — синтаксис и примерыГенераторы и yield в Python — как создавать и использоватьФункции в Python и способы их вызоваФункции как объекты в PythonЧто такое замыкания в PythonЧто делает функция reduce в PythonЧто делает функция id в PythonАргументы по умолчанию в PythonАнонимные функции и lambda в PythonАлгоритмы на Python — примеры и объяснение
Установка pip в PythonЗапись данных в PythonУправление зависимостями requirement в PythonУправление библиотеками с помощью Python PackagingУдаление пробелов с помощью strip в PythonСтруктурирование кода в PythonСоздание исполняемого файла Python в exeРазбор traceback в модуле PythonРазбор site-packages в PythonРазбор Program Files в PythonРабота с Unicode кодировками в PythonРабота с системными функциями Python sysРабота с папкой AppData в PythonРабота с модулем logging в PythonРабота с каталогами в PythonРабота с CSV в PythonВиртуальная среда venv в Python — создание и настройкаКак создать простое приложение на PythonИспользование pip в Python для установки пакетовМодули в Python и организация кода в проектеИмпорт модулей в Python и правила подключенияРабота с файлами в Python пошаговоЧто делает компилятор Python и как он работаетПолучение строки из модуля PythonПодключение файлов в Python с includeПеременные среды в PythonСборка проекта с помощью packaging в PythonНастройка Python сервераИспользование Python на UbuntuИспользование консоли PythonИспользование кодировок в PythonИнициализация пакетов PythonИмпорт модулей PythonИмпорт имен в PythonСреда IDLE Python и базовые возможностиЧтение и запись TXT в PythonЧтение файлов в Python с помощью open file
Удаление элементов из списка PythonТипы данных в Python — обзор и рекомендацииСписки в Python и их ключевые методыМетоды str в Python и обработка текстаОсновные операции со строками в PythonСоздание списков данных в PythonРабота со строками и символами в PythonРабота со столбцами в PythonРабота со списком значений в PythonРабота с таблицами в Python с помощью DataFrameРабота с RFR в PythonРабота с пробелами в PythonРабота с массивами в PythonРабота с кортежами tuple PythonРабота с координатами X и Y в PythonРабота с ключами в PythonРабота с элементами данных PythonРабота с двоичными числами PythonРабота с данными в PythonРабота с данными NumPy PythonРабота с большими числами в PythonРабота с битами в PythonРабота с байтами в PythonЧто такое значение в Python и как его определитьМножества в Python и операции с нимиИспользование range в Python для цикловПроверка на четность в PythonПроверка числа в PythonПреобразование типов в PythonПреобразование списка в строку PythonПреобразование числа в строку в PythonПостроение графиков в PythonОпределение индекса элемента в PythonОкругление чисел в PythonОбъединение списков в Python с помощью zipМножества в PythonМассивы в Python и отличие от списковМассив чисел в PythonКортежи данных в PythonКак вычислить сумму чисел в PythonКак получить остаток от деления в PythonКак найти следующее число в PythonИспользование Unicode в PythonТип int в Python и его особенностиИндекс списка в PythonФункции для работы со строками в PythonЭлементы Python и способы доступа к нимДоступ к элементам массива в PythonДеление чисел в PythonРабота с данными в Python на практикеКак работать с числами в Python
Открыть базу знаний

Лучшие курсы по теме

Иконка молнииНовый
изображение курса

Основы Python

Антон Ларичев
AI-тренажерыAI-тренажеры
Практика в студииПрактика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.7
3 999 ₽ 6 990 ₽
Подробнее
изображение курса

Nest.js с нуля

Антон Ларичев
AI-тренажерыAI-тренажеры
Практика в студииПрактика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.6
3 999 ₽ 6 990 ₽
Подробнее
изображение курса

Docker и Ansible

Антон Ларичев
AI-тренажерыAI-тренажеры
Гарантия
Бонусы
иконка звёздочки рейтинга4.7
3 999 ₽ 6 990 ₽
Подробнее

Отправить комментарий