Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Генераторы в 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 задачами.