Python Type Hints: пишем безопаснее и понятнее

Backend2026-09-13TryQuickToolBox

Вы, вероятно, сталкивались с функцией Python, которая возвращает разные типы в зависимости от входных данных, или с переменной, которая меняет тип на полпути. Такая неоднозначность приводит к ошибкам времени выполнения, которые можно было бы предотвратить. Аннотации типов Python решают эту проблему, позволяя указывать ожидаемые типы, делая код самодокументируемым и позволяя инструментам статического анализа выявлять ошибки до выполнения.

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

Что такое аннотации типов в Python?

Аннотации типов (также называемые подсказками типов) — это синтаксис, представленный в Python 3.5 (PEP 484), который позволяет указывать ожидаемые типы переменных, параметров функций и возвращаемых значений. Они не проверяются во время выполнения, но используются статическими анализаторами типов, такими как mypy, pyright и IDE, для обнаружения ошибок, связанных с типами.

Например:

def greet(name: str) -> str:
    return f"Hello, {name}"

Здесь name: str указывает, что name должен быть строкой, а -> str указывает, что функция возвращает строку.

Зачем использовать аннотации типов?

Базовые аннотации типов

Вы можете аннотировать переменные, параметры функций и возвращаемые типы.

Переменные

age: int = 30
name: str = "Alice"

Функции

def add(a: int, b: int) -> int:
    return a + b

Коллекции

Для списков, словарей и т.д. используйте модуль typing (или встроенные дженерики в Python 3.9+):

from typing import List, Dict

def process(items: List[str]) -> Dict[str, int]:
    return {item: len(item) for item in items}

В Python 3.9+ можно напрямую использовать list[str] и dict[str, int].

Продвинутые аннотации типов

По мере роста кода вы столкнетесь с более сложными сценариями. Вот некоторые продвинутые возможности.

Optional и Union

Optional[T] — это сокращение для Union[T, None], указывающее, что значение может быть типа T или None.

from typing import Optional

def find_user(user_id: int) -> Optional[str]:
    # возвращает имя пользователя или None, если не найдено
    ...

В Python 3.10+ можно использовать оператор |: str | None.

Callable

Для функций в качестве аргументов:

from typing import Callable

def apply_func(func: Callable[[int], int], value: int) -> int:
    return func(value)

Дженерики

Создавайте переиспользуемые компоненты с помощью переменных типа:

from typing import TypeVar, List

T = TypeVar('T')

def first(items: List[T]) -> T:
    return items[0]

TypedDict

Для словарей с фиксированным набором ключей и типов значений:

from typing import TypedDict

class User(TypedDict):
    name: str
    age: int

def greet(user: User) -> str:
    return f"Hello, {user['name']}"

Использование статических анализаторов типов

Аннотации типов полезны только в том случае, если вы их проверяете. Популярные инструменты включают mypy, pyright и pyre. Давайте посмотрим, как использовать mypy.

  1. Установите mypy: pip install mypy
  2. Запустите его на вашем коде: mypy your_script.py
  3. Исправьте сообщенные ошибки.

Например, для:

def add(a: int, b: int) -> int:
    return a + b

add("1", "2")

mypy сообщит: error: Argument 1 to "add" has incompatible type "str"; expected "int".

Вы можете настроить mypy с помощью файла mypy.ini или pyproject.toml, чтобы включить более строгие проверки.

Лучшие практики для аннотаций типов

Распространенные ошибки и как их избежать

Аннотации типов на практике: небольшой пример

Рассмотрим функцию, которая обрабатывает список чисел и возвращает среднее значение. Без аннотаций типов неясно, какие типы ожидаются.

def average(numbers):
    return sum(numbers) / len(numbers)

С аннотациями типов:

from typing import List

def average(numbers: List[float]) -> float:
    return sum(numbers) / len(numbers)

Теперь, если кто-то передаст список строк, mypy это отметит.

Интеграция аннотаций типов в ваш рабочий процесс

Чтобы получить максимальную пользу от аннотаций типов, интегрируйте их в процесс разработки:

  1. Постепенно добавляйте аннотации типов в существующие кодовые базы.
  2. Настройте IDE для отображения ошибок типов.
  3. Добавьте шаг проверки типов в ваш CI-конвейер.
  4. Используйте pre-commit хуки для запуска mypy перед коммитами.

Например, простой шаг рабочего процесса GitHub Actions:

- name: Type check
  run: mypy .

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

Влияют ли аннотации типов на производительность во время выполнения?

Нет, аннотации типов игнорируются во время выполнения. Они хранятся в __annotations__, но не влияют на скорость выполнения.

Могу ли я использовать аннотации типов в старых версиях Python?

Аннотации типов были введены в Python 3.5. Для более старых версий можно использовать аннотации на основе комментариев (например, # type: int), но рекомендуется перейти на поддерживаемую версию Python.

В чем разница между List и list в аннотациях типов?

List из typing используется в Python 3.5-3.8. В Python 3.9+ можно напрямую использовать встроенный list. Оба эквивалентны для проверки типов.

Готовы улучшить качество кода? Начните с добавления аннотаций типов к одной функции сегодня и запустите mypy, чтобы увидеть преимущества. Для получения дополнительных инструментов разработчика ознакомьтесь с нашим JSON Formatter, чтобы легко форматировать и проверять ваши данные JSON.