Menu
Русский

Аннотации типов в Python: type hints для функций, списков, словарей и не только

Что такое type hints в Python, когда они помогают и как аннотировать переменные, сигнатуры функций, контейнеры и опциональные значения.

Аннотации, которые описывают, но не навязывают

Type hint — это заметка на имя, обычно на параметр функции, говорящая «это должен быть int», «это возвращает список строк» и так далее. Во время выполнения Python их не проверяет. Передать строку туда, где объявлен int, — не ошибка. Редактор и внешние инструменты (mypy, pyright, Pyright через Pylance в VS Code) читают аннотации и предупреждают до запуска.

Самый простой случай:

main.py
Output
Click Run to see the output here.

name: str аннотирует параметр. -> str аннотирует возврат. Оба вызова выполняются. Второй неправильный — статический тайп-чекер его пометит, — но сам Python спокойно его обрабатывает, потому что 42 поддерживает интерполяцию f"{...}".

Ключевая ментальная модель: аннотации — документация, которую умеет читать машина. Они не меняют рантайм.

Зачем это нужно

Три конкретных выигрыша по скорости окупаемости:

  1. Редактор умнеет. Автодополнение показывает правильные методы, rename правильно распространяется, при наведении на переменную виден её тип.
  2. Сигнатуры становятся самодокументирующимися. def fetch(url: str, timeout: float = 5.0) -> dict: сообщает читателю, что передать и что он получит, — тело можно не читать.
  3. Тайп-чекеры ловят ошибки до запуска. mypy . по проекту всплывает баги, которые юнит-тесты часто пропускают: None там, где ждали значение, словарь там, где нужен список.

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

Базовые встроенные типы

Ни для одного из этих импортов не нужно:

main.py
Output
Click Run to see the output here.

Аннотации переменных (name: str = "Rosa") редко обязательны — Python выводит тип из правой части. Оставляй их для параметров, возвращаемых значений и случайных случаев, когда вывод неоднозначен.

Функции, ничего не возвращающие, используют -> None:

main.py
Output
Click Run to see the output here.

Списки, словари, кортежи и множества

Контейнерам нужен второй кусок информации — что они содержат. Современный Python позволяет подписывать встроенные типы напрямую:

main.py
Output
Click Run to see the output here.

Прочитаем вслух:

  • list[float] — список float-ов.
  • dict[str, int] — словарь со строковыми ключами и int-овыми значениями.
  • tuple[float, float] — кортеж ровно из двух float-ов.
  • set[str] — множество строк.

Подпись list[...], dict[...] работает в Python 3.9 и выше. В старом коде увидишь List, Dict, Tuple из typing — смысл тот же, написание старое.

Опциональные значения

«Может быть None» — частый случай. У него две равноценные записи — обе годятся, но новая читается приятнее:

main.py
Output
Click Run to see the output here.

str | None означает «строка или None». Синтаксис | работает в Python 3.10+. В старом коде увидишь Optional[str] из модуля typing — то же самое.

Увидев -> str | None, вызывающий знает, что надо проверить на None до использования результата, — собственно, ради этого аннотация и нужна.

Union: то или это

Когда значение может быть одного из нескольких типов, используй |:

main.py
Output
Click Run to see the output here.

Можно объединять больше двух типов. int | str | float — «любой из трёх».

Аннотация переменных внутри функций

В большинстве случаев Python сам выводит тип локальной переменной из инициализатора. Аннотация нужна только когда:

main.py
Output
Click Run to see the output here.
  • Контейнер стартует пустым, и тайп-чекер не может угадать содержимое.
  • Значение может быть нескольких типов, и ты хочешь зафиксировать один.
  • Хочется задокументировать намерение для человека.

typing.Any — аварийный люк: «не хочу точно аннотировать это». Используй скупо. Злоупотребление Any обесценивает остальные аннотации.

Аннотация классов

Атрибуты классов и сигнатуры методов аннотируются так же, как любая функция:

main.py
Output
Click Run to see the output here.

Dataclass-ы фактически требуют аннотаций — декоратор @dataclass читает их, чтобы сгенерировать __init__ и __repr__. Это единственное место, где аннотации влияют на рантайм.

Кортежи и «любая длина»

У tuple[...] две формы, которые путают новичков:

main.py
Output
Click Run to see the output here.
  • tuple[float, float] — ровно два float-а.
  • tuple[int, ...] — любое количество int-ов. ... (настоящий синтаксический элемент в системе типов) — «и так далее».

Callable и алиасы типов

Когда функция принимает или возвращает другую функцию — используй Callable:

main.py
Output
Click Run to see the output here.

Callable[[int], int] — «функция, принимающая один int и возвращающая int».

Когда аннотация повторяется, дай ей имя:

main.py
Output
Click Run to see the output here.

Алиас — это обычное присваивание Python. Везде, где ты бы использовал длинную форму, работает короткое имя.

Запускаем тайп-чекер

Интерпретатор Python аннотации игнорирует. Чтобы их проверить, установи тайп-чекер. mypy — оригинальный; pyright (который использует Pylance в VS Code) — быстрее.

pip install mypy
mypy your_project/

На первом прогоне всплывут ошибки в местах, о которых ты не догадывался. Работай с ними постепенно — # type: ignore заглушает одну конкретную строку, когда нужно двигаться дальше.

Современные IDE прогоняют проверку типов непрерывно по мере редактирования, так что большая часть обратной связи приходит ещё до сохранения.

Когда type hints не подходят

  • Быстрые исследовательские скрипты. Аннотации добавляют трения коду, который живёт час.
  • Сильно динамичный код. Метапрограммирование, плагинные системы и подобные паттерны часто перерастают то, что система типов способна описать. Аннотируй внешний API, а внутренности пусть будут свободнее.
  • Сторонние библиотеки без типов. Если у импортируемой библиотеки нет типовой информации, Any просачивается в твой код. Ок — это не твой код аннотировать.

Для всего между этих крайностей type hints — маленькая привычка с большой отдачей. Цена — несколько лишних нажатий на сигнатуру. Возврат — меньше багов, проще рефакторинги, код, документирующий сам себя.

Дальше: модули и импорты

Теперь у тебя весь функциональный инструментарий — аргументы, декораторы, аннотации типов. Дальше посмотрим, как Python раскладывает код по файлам: модули, пакеты и система импорта.

Часто задаваемые вопросы

Что такое type hints в Python?

Type hints — это аннотации, описывающие ожидаемые типы переменных, параметров функций и возвращаемых значений. Сам Python во время выполнения их не проверяет: они для инструментов (IDE, линтеров, тайп-чекеров вроде mypy или pyright) и для людей, читающих код.

Ускоряют ли type hints выполнение Python?

Нет. Интерпретатор Python игнорирует их во время выполнения. Ускорение — в цикле разработки: меньше опечаток ловит редактор, яснее сигнатуры, безопаснее рефакторинги.

Когда стоит добавлять type hints?

Добавляй в публичные сигнатуры функций — параметры и возвращаемые значения. Внутри тел — скупо, только там, где тип переменной не очевиден. Для одноразового скрипта они не обязательны; для общего кода и библиотек окупаются быстро.

Учитесь программировать с Coddy

НАЧАТЬ