← Назад к вопросам

Где используется механизм генераторов в Python?

2.3 Middle🔥 181 комментариев
#Python Core

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Использование механизма генераторов в Python

Генераторы — это один из мощнейших инструментов Python для работы с итерируемыми последовательностями. Они используются повсеместно для оптимизации памяти и улучшения производительности.

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

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

# Обычная функция возвращает список
def get_numbers_list():
    numbers = []
    for i in range(5):
        numbers.append(i)
    return numbers  # Возвращает ВСЕ значения сразу

result = get_numbers_list()
print(result)  # [0, 1, 2, 3, 4]

# Генератор возвращает значения по одному
def get_numbers_generator():
    for i in range(5):
        yield i  # Возвращает по одному значению

gen = get_numbers_generator()
print(next(gen))  # 0
print(next(gen))  # 1
print(next(gen))  # 2

Основные преимущества генераторов

  1. Экономия памяти — значения генерируются по мере необходимости
  2. Ленивые вычисления — не вычисляются лишние данные
  3. Работа с бесконечными последовательностями
  4. Быстрота — меньше операций за раз

Практические примеры использования

1. Работа с большими файлами

# ❌ Неправильно — загружает весь файл в память
def read_file_all(filepath):
    with open(filepath, r) as f:
        lines = f.readlines()  # Весь файл в памяти
    return lines

for line in read_file_all(large_file.txt):
    process_line(line)

# ✅ Правильно — читает строки по одной
def read_file_lines(filepath):
    with open(filepath, r) as f:
        for line in f:  # Генератор в for цикле
            yield line.strip()

for line in read_file_lines(large_file.txt):
    process_line(line)  # Обрабатывает по одной строке

2. Обработка больших наборов данных

# Чтение данных из БД порциями
def fetch_users_from_db(batch_size=100):
    offset = 0
    while True:
        users = database.query(User).offset(offset).limit(batch_size).all()
        if not users:
            break
        for user in users:
            yield user  # Выдаём по одному пользователю
        offset += batch_size

# Использование
for user in fetch_users_from_db():
    send_email(user.email)  # Обрабатываем по одному

3. Генерирование последовательностей

# Бесконечная последовательность натуральных чисел
def infinite_counter(start=0):
    while True:
        yield start
        start += 1

counter = infinite_counter()
print(next(counter))  # 0
print(next(counter))  # 1
print(next(counter))  # 2

# Числа Фибоначчи
def fibonacci():
    a, b = 0, 1
    while True:
        yield a
        a, b = b, a + b

fib = fibonacci()
for _ in range(10):
    print(next(fib))  # 0 1 1 2 3 5 8 13 21 34

4. Pipeline обработки данных

# Цепочка трансформаций данных
def read_data(filename):
    with open(filename) as f:
        for line in f:
            yield line

def filter_comments(lines):
    for line in lines:
        if not line.startswith(#):
            yield line

def parse_json(lines):
    for line in lines:
        try:
            yield json.loads(line)
        except json.JSONDecodeError:
            continue

# Использование
for data in parse_json(filter_comments(read_data(data.jsonl))):
    process(data)  # Обрабатываем по одному

5. Функции высшего порядка

# map с генератором
data = [1, 2, 3, 4, 5]
squared = map(lambda x: x ** 2, data)  # Это генератор
print(next(squared))  # 1
print(next(squared))  # 4

# filter с генератором
evens = filter(lambda x: x % 2 == 0, data)  # Это генератор
for num in evens:
    print(num)  # 2, 4

6. Web scraping с пагинацией

async def fetch_pages(base_url, max_pages):
    for page_num in range(1, max_pages + 1):
        url = f"{base_url}?page={page_num}"
        response = await fetch(url)
        if not response:
            break
        yield response.data

# Асинхронный обход всех страниц
async def main():
    async for page_data in fetch_pages(https://api.example.com/items, 100):
        process_page(page_data)  # Обрабатываем по одной странице

7. Параллельная обработка в Celery

# Отправка большого количества задач в Celery
def process_large_dataset(dataset_id):
    # Вместо отправления 1 миллиона задач сразу
    items = fetch_items(dataset_id)
    for item in items:  # items — это генератор
        process_task.delay(item.id)  # Отправляем по одной

Выражения-генераторы (Generator Expressions)

# Похоже на list comprehension, но с () вместо []
 squares = (x ** 2 for x in range(1000000))  # Генератор, не список
print(next(squares))  # 0

# Используется в функциях
sum_of_squares = sum(x ** 2 for x in range(1000000))  # Эффективно

# Фильтрация
evens = (x for x in range(1000000) if x % 2 == 0)

Два-способной генератор (Coroutine style)

def two_way_generator():
    print("Start")
    value = yield "First"
    print(f"Received: {value}")
    yield "Second"

gen = two_way_generator()
print(next(gen))  # Запускаем, выполняется до первого yield
result = gen.send("Hello")  # Отправляем значение и возобновляем
print(result)  # "Second"

Ключевые места использования

  1. Django ORMQuerySet использует генераторы
  2. NumPy/Pandas — обработка больших данных
  3. Web frameworks — потоковая передача больших файлов
  4. Celery — очередь задач
  5. asyncio — асинхронные генераторы
  6. itertools — встроенные генераторы для работы с последовательностями

Итоги

Генераторы используются:

  • Для экономии памяти при работе с большими данными
  • Для реализации ленивых вычислений
  • Для создания pipeline обработки данных
  • Во всех современных Python фреймворках и библиотеках
  • Для работы с асинхронным кодом

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

Где используется механизм генераторов в Python? | PrepBro