Слайд 2.1: Оператор yield и генераторы

Особенности работы с генераторами

Оператор yield позволяет создавать генераторы - специальные функции, которые могут приостанавливать своё выполнение и возобновлять его позже. Это особенно полезно при работе с последовательностями данных и в контекстных менеджерах.

1. Основы работы с yield:

# Обычная функция возвращает значение и завершается
def get_character_stats():
    return "ATK: 1500"

# Функция с yield может возвращать значения по одному
def get_character_stats_generator():
    yield "ATK: 1500"
    yield "DEF: 800"
    yield "HP: 15000"

# Использование
stats = get_character_stats_generator()
print(next(stats))  # "ATK: 1500"
print(next(stats))  # "DEF: 800"
print(next(stats))  # "HP: 15000"

2. Использование в циклах:

# Генератор для перебора артефактов
def artifact_stats():
    artifact = {
        "Цветок": "HP+4780",
        "Перо": "ATK+311",
        "Часы": "ATK%+46.6"
    }
    
    for piece, stat in artifact.items():
        yield f"{piece}: {stat}"

# Использование в цикле for
for stat in artifact_stats():
    print(stat)  # Выводит статы по одной

3. Экономия памяти:

# Без yield - создаёт весь список сразу
def get_all_enemies():
    enemies = []
    for level in range(1, 101):
        enemies.append(f"Хиличурл ур.{level}")
    return enemies

# С yield - создаёт по одному врагу при необходимости
def enemy_generator():
    for level in range(1, 101):
        yield f"Хиличурл ур.{level}"

# Разница в использовании памяти
all_enemies = get_all_enemies()  # Создаёт список из 100 врагов
enemies = enemy_generator()      # Создаёт только генератор
for enemy in enemies:           # Создаёт по одному врагу за раз

4. Передача управления:

# Симуляция боя с передачей управления
def combat_simulator():
    # Подготовка к бою
    yield "Бой начинается"
    
    # Первый ход
    damage = 1500
    yield f"Нанесено {damage} урона"
    
    # Второй ход
    healing = 1000
    yield f"Восстановлено {healing} HP"
    
    # Завершение боя
    yield "Бой окончен"

# Использование
battle = combat_simulator()
print(next(battle))  # "Бой начинается"
print(next(battle))  # "Нанесено 1500 урона"
print(next(battle))  # "Восстановлено 1000 HP"
print(next(battle))  # "Бой окончен"

Важно помнить:

  • yield временно приостанавливает выполнение функции
  • Функция с yield называется генератором
  • Генератор помнит своё состояние между вызовами
  • Генераторы экономят память при работе с большими наборами данных
  • После последнего yield генератор вызовет StopIteration

Задача: Система фарма материалов

Создайте генератор для симуляции фарма материалов возвышения:

Подсказка: Пример структуры генератора:

def domain_farm_simulator(target_amount: int):
    """Симулятор фарма в домене"""
    resin = 160
    materials = 0
    
    while materials < target_amount and resin >= 20:
        resin -= 20
        drops = random.randint(2, 3)
        materials += drops
        yield {
            "получено": drops,
            "всего": materials,
            "осталось_смолы": resin
        }