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

Для чего нужен генератор в Python?

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

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

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

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

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

Генератор в Python — это функция, которая возвращает значения одно за другим, вместо того чтобы вернуть весь результат сразу. Она использует оператор yield вместо return. Генераторы очень полезны в автоматизации тестирования.

Зачем нужны генераторы

1. Экономия памяти (Memory Efficiency)

Генератор не создаёт весь список в памяти сразу. Он генерирует значение по требованию — лишь тогда, когда оно нужно.

# Плохо — создаёт список из 1 миллиона элементов в памяти
def get_numbers(n):
    result = []
    for i in range(n):
        result.append(i)
    return result

numbers = get_numbers(1000000)  # ОС может не хватить памяти!

# Хорошо — генератор не держит всё в памяти
def get_numbers_generator(n):
    for i in range(n):
        yield i

numbers = get_numbers_generator(1000000)  # Практически не потребляет память!
for num in numbers:
    process(num)

2. Ленивые вычисления (Lazy Evaluation)

Значение вычисляется только когда оно нужно. Это полезно для бесконечных последовательностей или дорогих вычислений.

# Бесконечная последовательность чисел Фибоначчи
def fibonacci():
    a, b = 0, 1
    while True:
        yield a
        a, b = b, a + b

fib = fibonacci()
print(next(fib))  # 0
print(next(fib))  # 1
print(next(fib))  # 1
print(next(fib))  # 2
print(next(fib))  # 3
# Можно продолжать бесконечно!

3. Производительность

Генераторы работают быстрее, потому что не нужно создавать весь список, сортировать его и т.д. Просто генерируем то, что нужно сейчас.

Как работает генератор

  1. Функция с yield вызывается, возвращает объект генератора (функция ещё НЕ выполняется!)
  2. next() вызывает функцию, она выполняется до первого yield
  3. yield возвращает значение и приостанавливает выполнение функции
  4. При следующем вызове next() функция продолжает с того же места, где остановилась
  5. StopIteration выбрасывается, когда функция заканчивается
def simple_generator():
    print("Start")
    yield 1
    print("Between 1 and 2")
    yield 2
    print("Between 2 and 3")
    yield 3
    print("End")

gen = simple_generator()  # Функция ещё НЕ запустилась!

print(next(gen))  
# Выведет: Start
# Вернёт: 1

print(next(gen))  
# Выведет: Between 1 and 2
# Вернёт: 2

print(next(gen))  
# Выведет: Between 2 and 3
# Вернёт: 3

print(next(gen))  
# Выведет: End
# Выбросит: StopIteration exception

Использование генераторов в QA-тестировании

Генераторы очень полезны при тестировании:

Генератор тестовых данных

def generate_test_users():
    for i in range(1000):
        yield {
            "id": i,
            "name": f"User {i}",
            "email": f"user{i}@test.com",
            "age": 20 + i % 50
        }

@pytest.mark.parametrize("user", generate_test_users())
def test_create_user(user):
    response = requests.post("/users", json=user)
    assert response.status_code == 201
    assert response.json()["email"] == user["email"]

Чтение больших файлов

def read_large_csv_file(filename):
    with open(filename, 'r') as f:
        for line in f:
            yield line.strip()

def test_parse_csv():
    for line in read_large_csv_file('test_data.csv'):
        fields = line.split(',')
        assert len(fields) == 5

Генератор для тестирования API с пагинацией

def fetch_all_users_paginated(base_url, page_size=50):
    page = 1
    while True:
        response = requests.get(f"{base_url}/users?page={page}&size={page_size}")
        users = response.json()
        if not users:
            break
        for user in users:
            yield user
        page += 1

def test_all_users_have_email():
    for user in fetch_all_users_paginated("http://api.example.com"):
        assert "email" in user
        assert "@" in user["email"]

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

Есть также генераторные выражения — как list comprehension, но с круглыми скобками вместо квадратных:

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

# Generator expression — ленивое, экономит память
squares = (x**2 for x in range(1000000))

# Использование с sum() — генератор эффективнее
sum([x**2 for x in range(1000000)])      # Медленнее, много памяти
sum(x**2 for x in range(1000000))        # Быстрее, мало памяти!

# Filter с генератором
even_numbers = (x for x in range(1000000) if x % 2 == 0)

Выводы

Генераторы в Python идеальны для:

  • Экономии памяти при работе с большими объёмами данных
  • Ленивых вычислений (вычисли только то, что нужно сейчас)
  • Бесконечных последовательностей
  • Улучшения производительности

В автоматизации тестирования генераторы помогают эффективно работать с большими наборами тестовых данных и кэшировать результаты по мере необходимости.