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

Что такое генератор в Python?

1.3 Junior🔥 191 комментариев
#Python

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

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

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

Генераторы в Python

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

Основное отличие от обычной функции

Обычная функция:

def numbers():
    return [1, 2, 3, 4, 5]  # Создаёт весь список в памяти

result = numbers()
print(result)  # [1, 2, 3, 4, 5]

Генератор:

def numbers():
    yield 1  # yield вместо return
    yield 2
    yield 3
    yield 4
    yield 5

gen = numbers()
print(next(gen))  # 1
print(next(gen))  # 2

Ключевая концепция: yield

yield приостанавливает функцию и возвращает значение. При следующем вызове next() функция продолжается с того же места.

def my_generator():
    print("Начало")
    yield 1
    print("После первого yield")
    yield 2
    print("После второго yield")
    yield 3
    print("Конец")

gen = my_generator()
print(next(gen))      # Выведет: "Начало" затем 1
print(next(gen))      # Выведет: "После первого yield" затем 2
print(next(gen))      # Выведет: "После второго yield" затем 3
print(next(gen))      # StopIteration исключение

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

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

# Обычный способ: создаём весь список
data = [x**2 for x in range(1000000)]
print(len(data))  # 1,000,000 элементов в памяти

# Генератор: генерирует по одному
def squares():
    for x in range(1000000):
        yield x**2

gen = squares()
print(next(gen))  # Всегда в памяти только одно значение

2. Ленивое вычисление (lazy evaluation)

def read_large_file(filepath):
    with open(filepath) as f:
        for line in f:
            yield line.strip()  # Читает по одной строке

# Обрабатываем файл построчно
for line in read_large_file('huge_file.txt'):
    process(line)  # Используем строку

3. Бесконечные последовательности

def infinite_counter():
    n = 0
    while True:
        yield n
        n += 1

for i, value in enumerate(infinite_counter()):
    print(value)
    if i >= 5:  # Остановимся на 6-м
        break

Примеры использования в Data Science

1. Batch generator для глубокого обучения

def batch_generator(X, y, batch_size=32):
    for i in range(0, len(X), batch_size):
        yield X[i:i+batch_size], y[i:i+batch_size]

# Использование
for X_batch, y_batch in batch_generator(X_train, y_train, batch_size=64):
    model.train_on_batch(X_batch, y_batch)

2. Чтение CSV файла по частям

import pandas as pd

def read_csv_chunks(filepath, chunksize=10000):
    reader = pd.read_csv(filepath, chunksize=chunksize)
    for chunk in reader:
        yield chunk

# Обработка больших файлов
for df_chunk in read_csv_chunks('large_data.csv'):
    process_data(df_chunk)

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

def data_pipeline(data):
    # Фильтрация
    filtered = (x for x in data if x > 0)
    
    # Преобразование
    squared = (x**2 for x in filtered)
    
    # Normalization
    normalized = (x / 100 for x in squared)
    
    return normalized

data = range(-10, 10)
for value in data_pipeline(data):
    print(value)

Генераторные выражения (Generator Expressions)

Аналог list comprehension, но создаёт генератор:

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

# Generator expression — элементы по одному
gen_expr = (x**2 for x in range(1000000))
print(next(gen_expr))  # 0
print(next(gen_expr))  # 1

# Или через цикл
for val in gen_expr:
    print(val)

Двусторонние генераторы (send)

Генератор может получать значения через send():

def echo_generator():
    value = None
    while True:
        value = (yield value)  # Принимаем значение от send()

gen = echo_generator()
next(gen)  # Инициализация
print(gen.send(10))  # 10
print(gen.send(20))  # 20
print(gen.send(30))  # 30

Практический пример: обработка потока данных

def temperature_sensor():
    """Имитирует датчик температуры"""
    import random
    while True:
        yield random.uniform(20, 30)

def moving_average(sensor_stream, window=5):
    """Скользящее среднее"""
    buffer = []
    for temp in sensor_stream:
        buffer.append(temp)
        if len(buffer) > window:
            buffer.pop(0)
        yield sum(buffer) / len(buffer)

def alert_on_threshold(data_stream, threshold=28):
    """Оповещение при превышении порога"""
    for value in data_stream:
        if value > threshold:
            yield f"ALERT: Temperature {value} exceeds {threshold}"
        else:
            yield f"Normal: {value}"

# Pipeline
sensor = temperature_sensor()
avg = moving_average(sensor)
alerts = alert_on_threshold(avg)

for i in range(100):
    print(next(alerts))

Важные методы

gen = (x for x in range(5))

# next() — получить следующее значение
print(next(gen))  # 0

# for — итерировать
for val in gen:
    print(val)  # 1, 2, 3, 4

# list() — преобразовать в список
gen = (x for x in range(5))
print(list(gen))  # [0, 1, 2, 3, 4]

Заключение

Генераторы — это essential инструмент в Python для:

  • Работы с большими данными
  • Оптимизации памяти
  • Создания elegant data pipelines
  • Реализации бесконечных последовательностей

Они делают код более читаемым и эффективным, особенно при работе с data science задачами.