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

«Что такое генератор в Python?» — вопрос из категории Python, который задают на 35% собеседований AQA / Automation. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

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

Ключевое отличие от обычной функции:

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

Пример 1: Генератор для создания тестовых данных:

def generate_test_users(count):
    """Генератор, создающий словари с тестовыми пользователями."""
    for i in range(1, count + 1):
        # Не создаем список из всех пользователей, а генерируем по одному
        yield {
            "id": i,
            "username": f"test_user_{i}",
            "email": f"user{i}@test.com"
        }

# Использование в тесте (например, для параметризации)
for user in generate_test_users(10000):  # Не займет много памяти даже для 10к пользователей
    # Отправляем POST-запрос на создание пользователя
    response = requests.post("/api/users", json=user)
    assert response.status_code == 201
    print(f"Created user: {user['username']}")

Пример 2: Генератор для чтения больших лог-файлов построчно:

def read_large_log(file_path):
    """Генератор для чтения большого файла построчно без загрузки в память целиком."""
    with open(file_path, 'r') as file:
        for line in file:
            if "ERROR" in line:  # Фильтрация на лету
                yield line.strip()

# Поиск ошибок в огромном лог-файле
for error_line in read_large_log("application.log"):
    # Анализируем каждую ошибку, не загружая весь файл
    log_error_to_test_report(error_line)

Генераторные выражения (generator expression): Краткая форма создания генераторов, похожая на list comprehension, но в круглых скобках.

# List comprehension (создает список в памяти)
squares_list = [x**2 for x in range(1000000)]  # Много памяти!

# Generator expression (ленивое вычисление)
squares_gen = (x**2 for x in range(1000000))  # Практически не занимает памяти
print(next(squares_gen))  # 0
print(next(squares_gen))  # 1
# ...

Практическое применение в тестировании:

  1. Параметризация тестов: Генерация уникальных тестовых данных для каждого прогона.
  2. Чтение/запись больших файлов: Обработка дампов БД, логов, CSV-отчетов.
  3. Имитация потоков данных: Для нагрузочного тестирования API, где нужно постепенно подавать данные.

Видео-ответы