← Назад к вопросам
Где используется механизм генераторов в 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. Работа с большими файлами
# ❌ Неправильно — загружает весь файл в память
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"
Ключевые места использования
- Django ORM —
QuerySetиспользует генераторы - NumPy/Pandas — обработка больших данных
- Web frameworks — потоковая передача больших файлов
- Celery — очередь задач
- asyncio — асинхронные генераторы
- itertools — встроенные генераторы для работы с последовательностями
Итоги
Генераторы используются:
- Для экономии памяти при работе с большими данными
- Для реализации ленивых вычислений
- Для создания pipeline обработки данных
- Во всех современных Python фреймворках и библиотеках
- Для работы с асинхронным кодом
Это один из ключевых инструментов профессионального Python разработчика.