Урок курса

Type hints и mypy в Python: практическая типизация

Python для продвинутых: ООП, типизация и тестирование

Type hints описывают ожидаемые типы для разработчика, IDE и статического анализатора. Интерпретатор Python обычно не запрещает передать значение другого типа, поэтому аннотация — контракт для анализа, а не встроенная runtime-валидация.

def total(prices: list[float], discount: float = 0.0) -> float:
    return sum(prices) * (1 - discount)

Mypy анализирует код без запуска и находит несовместимые аргументы, отсутствующие ветки и неправильные возвращаемые значения. Его полезно запускать в CI с одной зафиксированной конфигурацией, иначе локальная проверка и pipeline будут расходиться.

Optional и сужение типа

Тип str | None означает два реальных состояния. До вызова методов строки нужно сузить тип проверкой.

def normalize(name: str | None) -> str:
    if name is None:
        return "anonymous"
    return name.strip().lower()

Не используйте Optional как синоним необязательного аргумента: он говорит именно о допустимом None. Аргумент может быть необязательным из-за значения по умолчанию, но при этом никогда не принимать None.

Для конечного набора строк полезен Literal, для структурных интерфейсов — Protocol, для обобщённых контейнеров — type parameters. Начинайте с сигнатур на границах модулей, не пытаясь за один день аннотировать весь legacy-код.

Где заканчивается статическая типизация

Данные из JSON, формы или базы остаются недоверенными. Анализатор верит объявленной сигнатуре функции загрузки, но не проверяет содержимое HTTP-ответа во время работы. На внешней границе нужна runtime-валидация; после неё типизированный объект можно безопаснее передавать внутри системы.

Избегайте широкого Any: он выключает проверку и распространяется по вызовам. Если тип пока неизвестен, object заставляет явно проверить его перед использованием. Точечный # type: ignore[code] лучше безусловного ignore, потому что фиксирует конкретное исключение.

Цель mypy — не максимальное число аннотаций, а более дешёвое изменение кода. Типы особенно окупаются в публичных функциях, моделях состояния и местах, где много вариантов результата.

Аннотация типа не проверяет вход во время выполнения

У функции ниже есть аннотация str, но обычный Python не запрещает передать число. Ошибка появляется лишь когда код пытается вызвать строковый метод. Статический анализатор может заметить неправильный вызов до запуска; исполнение и статическая проверка — разные этапы.

def normalize_name(name: str) -> str:
    return name.strip().lower()
assert normalize_name("  ANNA ") == "anna"
try:
    normalize_name(123)
except AttributeError:
    print("Аннотация не преобразовала число в строку")

Сохраните код в файл и добавьте неверный вызов без try для проверки mypy. При входе из сети нельзя полагаться только на результат статического анализа своего кода: JSON поступает от внешнего клиента. Проверяйте схему на границе приложения, а внутри используйте проверенные типы. Optional[str] описывает допустимость None, но не назначает аргументу значение по умолчанию.

Продолжите разбор: Dataclass, NamedTuple или обычный класс в Python.

Задача 1

Что означает аннотация str | None?

Выберите один вариант
Без регистрации · результат не сохраняется

Продолжить с сохранением прогресса

Перейдите к уроку в учебном кабинете.

Перейти к интерактивному уроку