Что такое ключевое слово yield?

Ответ

yield — это ключевое слово в Python, используемое для создания генераторов. Функция, содержащая yield, возвращает специальный итератор — генератор, который выдаёт значения по одному, приостанавливая своё выполнение после каждого yield и сохраняя локальное состояние для последующего возобновления.

Пример простого генератора:

def countdown(n):
    print("Starting countdown from", n)
    while n > 0:
        yield n  # Возвращает значение и приостанавливается
        n -= 1
    print("Done!")

# Использование
for i in countdown(5):
    print(i)
# Вывод: 5, 4, 3, 2, 1

Ключевые преимущества:

  • Ленивые вычисления: Значения генерируются "на лету", а не хранятся в памяти целиком, что эффективно для работы с большими или бесконечными последовательностями.
  • Сохранение состояния: Функция-генератор "помнит" своё место между вызовами.

Практическое применение в тестировании: Генераторы полезны для:

  1. Создания тестовых данных: Генерация большого потока данных для нагрузочного или стресс-тестирования без потребления всей оперативной памяти.

    def generate_test_ids(start):
        id = start
        while True:
            yield f"user_{id}"
            id += 1
    
    id_gen = generate_test_ids(1000)
    test_user_ids = [next(id_gen) for _ in range(10000)]  # 10k ID
  2. Имитации потокового ввода/вывода в интеграционных тестах.
  3. Реализации кастомных итераторов для объектов сложной структуры, которые необходимо последовательно проверять в тестах.

Ответ 18+ 🔞

Давай разжую про yield, а то смотрю, у некоторых глаза уже стекленеют, как у пьяного хомяка. Представь, что обычная функция — это бутылка водки: открыл, хлопнул до дна — и всё, пусто, кайф закончился. А функция с yield — это волшебная бутылка, которая сама тебе наливает стопку, ставит обратно на полку и ждёт, пока ты попросишь ещё. Не выпиваешь всё сразу, а растягиваешь удовольствие, и главное — она помнит, сколько уже отлила. Ёпта, вот это технологии!

Смотри, вот простейший пример, чтоб мозг не взорвался:

def countdown(n):
    print("Стартуем отсчёт с", n)
    while n > 0:
        yield n  # Вот тут магия! Отдал цифру и уснул до следующего раза.
        n -= 1
    print("Всё, приехали!")

Используется это чудо просто:

for i in countdown(5):
    print(i)
# Напечатает: 5, 4, 3, 2, 1

В чём, блядь, соль, спросишь ты?

  • Ленивость, мать её: Не нужно грузить в память овердохуища данных сразу. Значения появляются по мере надобности, как горячие пирожки. Идеально, если у тебя поток данных размером с Камаз, а память — как у золотой рыбки.
  • Память, как у слона: Генератор не страдает склерозом. Он чётко помнит, на каком шаге остановился, и все свои локальные переменные. Красота!

А где это применить в тестах, чтобы не выглядеть конченым идиотом?

  1. Нагенерировать тестовых данных, чтоб глаза вылезли. Например, бесконечную ленту юзеров для нагрузочного теста, без попытки сразу сожрать всю оперативку.

    def generate_test_ids(start):
        id = start
        while True:
            yield f"user_{id}"
            id += 1
    
    id_gen = generate_test_ids(1000)
    # Берём 10 тысяч айдишников, а не миллион сразу. Умно, да?
    test_user_ids = [next(id_gen) for _ in range(10000)]
  2. Сымитировать чтение из файла или сокета по чуть-чуть, как будто данные прут медленно, с перебоями. Проверить, не сломается ли твой код, если ему давать инфу по крупицам.
  3. Сделать кастомный обходчик для своей ебанутой структуры данных, чтобы в тестах прогонять по ней проверки последовательно, не вынося себе мозг.

Короче, yield — это не какая-то мартышлюшка для задротов, а реально хитрая жопа, которая экономит память и делает код элегантнее. Освой — и будешь выглядеть на фоне коллег, как хипстер на сельской дискотеке.