Найти в Дзене

Проверка типов в Python: как сделать код надежнее

Python — язык с динамической типизацией. Это значит, что нам не нужно указывать тип переменной, когда мы её создаем. Интерпретатор сам понимает, что x = 10 — это число, а name = "Анна" — это строка. Это удобно и позволяет писать код быстро. Но у медали есть обратная сторона: ошибки, связанные с типами данных, могут проявиться в самый неподходящий момент — во время выполнения программы. В Python есть принцип: "Если это выглядит как утка и крякает как утка, то это утка". Мы можем передать в функцию любой объект, главное, чтобы у него был нужный метод. Представьте функцию, которая приветствует пользователя (см. рис. ниже). Эта функция отлично работает, если передать ей строку: print(greet("Максим")) # Вывод: Привет, Максим! Но что, если передать число? print(greet(500)) Мы получим ошибку: TypeError: can only concatenate str (not "int") to str. Интерпретатор пытался сложить строку и число, но не смог. Программа упала. Самый простой способ — вручную проверять типы внутри функции с помощью
Оглавление

Python — язык с динамической типизацией. Это значит, что нам не нужно указывать тип переменной, когда мы её создаем. Интерпретатор сам понимает, что x = 10 — это число, а name = "Анна" — это строка.

Это удобно и позволяет писать код быстро. Но у медали есть обратная сторона: ошибки, связанные с типами данных, могут проявиться в самый неподходящий момент — во время выполнения программы.

Проблема "Утиной типизации"

В Python есть принцип: "Если это выглядит как утка и крякает как утка, то это утка". Мы можем передать в функцию любой объект, главное, чтобы у него был нужный метод.

Представьте функцию, которая приветствует пользователя (см. рис. ниже).

Эта функция отлично работает, если передать ей строку:

print(greet("Максим")) # Вывод: Привет, Максим!

Но что, если передать число?

print(greet(500))

Мы получим ошибку: TypeError: can only concatenate str (not "int") to str. Интерпретатор пытался сложить строку и число, но не смог. Программа упала.

Как это лечится?

Самый простой способ — вручную проверять типы внутри функции с помощью функции isinstance().

-2

Теперь программа не упадет с ошибкой, а вежливо сообщит о проблеме. Однако такой код становится более громоздким, особенно если проверять приходится много аргументов.

Современный подход: Type Hints (подсказки типов)

Начиная с Python 3.5, в язык добавили механизм подсказок типов (type hints). Это способ указать, какого типа данные ожидает функция.

Главное преимущество: подсказки типов не влияют на работу программы (интерпретатор их игнорирует), но они невероятно полезны для программиста и для сторонних инструментов.

Давайте перепишем нашу функцию:

-3

Что мы сделали:

  • user: str — мы подсказали, что аргумент user должен быть строкой.
  • -> str — мы подсказали, что функция вернет строку.

Если теперь мы вызовем greet(500), программа снова упадет с той же ошибкой! Почему? Потому что Python по-прежнему не проверяет типы во время работы. Это просто краткая подсказка программисту, чтобы он помнил, какие типы данных использует функция.

Как заставить это работать? МойPy (mypy)

Чтобы подсказки типов приносили реальную пользу, нужен дополнительный инструмент — статический анализатор кода. Самый популярный из них называется mypy.

Его нужно установить один раз (через командную строку):

pip install mypy

А затем запустить проверку нашего файла (например, test.py). Это тоже делается в командной строке:

mypy test.py

И тут mypy выдаст ошибку, не запуская саму программу:

main.py:4: error: Argument 1 to "greet" has incompatible type "int"; expected "str"

Мы нашли ошибку еще до того, как пользователь столкнулся с ней в работающем приложении:

-4

Простой и полный пример

Давайте посмотрим на более сложный пример: функцию сложения двух чисел.

Плохой вариант (без подсказок):

-5

Хороший вариант (с подсказками и mypy):

-6

Запустим проверку mypy:

mypy calculator.py
# Success: no issues found in 1 source file

Если мы заменим вызов на add("10", "5"), то получим ошибку на этапе анализа кода, и программа даже не запустится до исправления.

Заключение

Проверка типов в Python — это не встроенная функция языка, а культура программирования.

  1. Динамическая типизация дает гибкость.
  2. Ручная проверка (isinstance) защищает от падений, но "зашумляет" код.
  3. Подсказки типов (Type Hints) делают код самодокументированным и понятным.
  4. Mypy отлавливает ошибки типов до того, как программа попадёт к пользователю.

Используйте подсказки типов в своих проектах — это сделает код чище, а вас увереннее в его надежности.

На этом всё. Подписывайтесь на канал, чтобы ничего не пропустить.