Слайд 2: Типы параметров функций

1. Обязательные позиционные параметры:

  • Должны передаваться при каждом вызове функции
  • Должны передаваться в том же порядке, в котором объявлены
  • Не имеют значений по умолчанию
# base_atk и talent_level - обязательные позиционные параметры
def calculate_damage(base_atk, talent_level):
    return base_atk * talent_level

# Правильный вызов:
damage = calculate_damage(1500, 6)

# Также можно указать имена, сохраняя порядок:
damage = calculate_damage(base_atk=1500, talent_level=6)

2. Необязательные параметры (со значением по умолчанию):

  • Имеют значение по умолчанию после =
  • Могут не указываться при вызове
  • Могут быть как позиционными, так и именованными
# crit_rate и crit_dmg - необязательные параметры
def calculate_crit(base_dmg, crit_rate=0.05, crit_dmg=0.5):
    return base_dmg * (1 + crit_rate * crit_dmg)

# Разные способы вызова:
damage1 = calculate_crit(1000)  # Используются значения по умолчанию
damage2 = calculate_crit(1000, 0.7)  # Позиционно
damage3 = calculate_crit(1000, crit_dmg=0.8)  # По имени

3. Только именованные параметры (после *):

  • Могут быть как обязательными, так и необязательными
  • Должны всегда передаваться по имени
  • Порядок при вызове не важен
# element - обязательный именованный параметр
# multiplier - необязательный именованный параметр
def cast_skill(base_dmg, *, element, multiplier=1.0):
    return base_dmg * multiplier

# Правильные вызовы:
damage1 = cast_skill(1000, element="Анемо")
damage2 = cast_skill(1000, element="Анемо", multiplier=1.5)
damage3 = cast_skill(1000, multiplier=1.5, element="Анемо")

# Ошибка: element должен быть именованным
# damage4 = cast_skill(1000, "Анемо")  # TypeError

4. *args и **kwargs:

  • *args принимает любое количество позиционных аргументов
  • **kwargs принимает любое количество именованных аргументов
# *args - произвольное число значений урона
def calculate_combo(*damage_values):
    return sum(damage_values)

combo = calculate_combo(100, 150, 200)  # 450

# **kwargs - произвольное число баффов
def apply_buffs(base_dmg, **buffs):
    total = base_dmg
    for buff_name, value in buffs.items():
        total *= (1 + value)
    return total

# Применяем разные баффы
damage = apply_buffs(
    1000,
    pyro_resonance=0.25,
    noblesse=0.2,
    bennett=0.8
)

5. Аннотации типов:

  • Помогают документировать ожидаемые типы данных
  • Улучшают читаемость кода
  • Помогают находить ошибки при разработке
from typing import List, Optional, Dict

def calculate_damage(
    base_atk: float,
    multipliers: List[float],
    elemental_bonus: Optional[float] = None,
    *,
    resistances: Dict[str, float] = {}
) -> float:
    """
    Рассчитывает урон с учетом всех множителей.
    
    Args:
        base_atk: Базовая атака
        multipliers: Список множителей урона
        elemental_bonus: Бонус элементального урона
        resistances: Словарь сопротивлений противника
    
    Returns:
        float: Итоговый урон
    """
    total = base_atk
    for mult in multipliers:
        total *= mult
    if elemental_bonus:
        total *= (1 + elemental_bonus)
    return total

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

  • Обязательные параметры всегда идут первыми
  • После * все параметры должны быть именованными
  • Значения по умолчанию вычисляются один раз при определении функции
  • Аннотации типов помогают предотвращать ошибки, но не проверяются автоматически
  • *args и **kwargs используются, когда число параметров заранее неизвестно