Аннотации переменных в Python 3

| Python

В Python версии 3.6 добавлен синтаксис аннотаций переменных. Аннотации переменных – это в основном, усовершенствование подсказки типа переменных, которые были представлены в Python 3.5. Обстоятельное объяснение аннотаций переменных представлено в PEP 526. В этой статье будет кратко рассказано о подсказках типов, а затем рассмотрен новый синтаксис аннотаций переменных.

Что такое подсказка типа?

Подсказка типа в Python в основном сообщает о том, какими типами обладают аргументы и параметры в функциях и методах. Python не использует подсказки типов, но их можно задействовать в инструменте mypy, для применения подсказок типов подобным образом, как и в C ++ принудительно определяющий объявления типов во время выполнения. Рассмотрим обычную функцию без добавления новых подсказок:

def add(a, b):
    return a + b

if __name__ == '__main__':
    add(2, 4)

Здесь представлена простая функция add(), которая принимает два параметра. Она складывает оба параметра и возвращает результат. Её код не предписывает проверку типов переменных передаваемых в функцию. Можно передать ей целые числа, флоаты, списки или строки, и она, скорее всего, сработает. Но будет ли она работать так, как ожидается? Добавим подсказки типов в скрипт:

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

if __name__ == '__main__':
    print(add(2, 4))

Здесь изменено определение функции с использованием подсказок типов. Теперь параметры типизированы:

  • a: int
  • b: int

Также намекаем на возвращаемое значение «-> int». Это означает, что ожидается целое число как возвращаемое значение. Если попытаться вызвать функцию add() с помощью пары строк или float и целого числа, то к ошибке это не приведёт. Как уже было сказано, Python позволяет намекать на то, какой тип параметров должен быть, но не обеспечивая его проверку.

Обновим код до следующего:

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

if __name__ == '__main__':
    print(add(5.0, 4))

Если запустить его интерпретатором CPython, то он выполняется без ошибок. Теперь установим mypy, используя pip:

pip install mypy

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

mypy hints.py

После запуска этой команды, получен следующий результат:

hints.py:5: error: Argument 1 to "add" has incompatible type "float"; expected "int"

mypy обнаружил проблему с нашим кодом. Происходит передача float в первом аргументе вместо int. Можете использовать mypy на сервере непрерывной интеграции, который может проверить код на эти проблемы, прежде чем совершать коммит и пуш в ветку, или запускать его локально, прежде чем коммитить код.

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

Предположим, что нужно не просто комментировать параметры функции, но также и обычные переменные. В Python 3.5 используя тот же синтаксис, что и для параметров функции недопустимо, поскольку вызовет исключение SyntaxError. Вместо этого нужно использовать комментарии, а начиная с версии 3.6 можно использовать новый синтаксис! Рассмотрим пример:

from typing import List

def odd_numbers(numbers: List) -> List:
    odd: List[int] = []
    for number in numbers:
        if number % 2:
            odd.append(number)

    return odd

if __name__ == '__main__':
    numbers = list(range(10))
    print(odd_numbers(numbers))

Здесь конкретизируется, что переменная odd должна быть списком целых чисел. Если запустить mypy с этим скриптом, то не получим сообщения об ошибке. Попробуем изменить код, чтобы добавить что-то отличное от целого.

from typing import List

def odd_numbers(numbers: List) -> List:
    odd: List[int] = []
    for number in numbers:
        if number % 2:
            odd.append(number)

    odd.append('foo')

    return odd

if __name__ == '__main__':
    numbers = list(range(10))
    print(odd_numbers(numbers))

Здесь добавлена новая строка, которая помещает строку в список целых чисел. Теперь, если запустить mypy с данной версией кода, увидим следующее:

hints2.py:9: error: Argument 1 to "append" of "list" has incompatible type "str"; expected "int"

Повторимся, в Python 3.5 можно сделать аннотацию переменной, но для этого нужно поместить эту аннотацию в комментарий:

# Python 3.6
odd: List[int] = []

# Python 3.5
odd = [] # type: List[int]

Обратите внимание: если вы измените код, чтобы использовать синтаксис аннотации переменной в Python 3.5, mypy по-прежнему будет корректно находить ошибку. Нужно указать «type:» после знака диеза. Если удалить его, то это уже не аннотация переменной. В основном все новые возможности PEP 526 делают синтаксис языка более однородным.

Вывод

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