Как/почему работает синтаксис подсказки типа Python?

Я только что видел следующий пример в PEP 484< /а>:

def greeting(name: str) -> str:
    return 'Hello ' + name

print(greeting('Martin'))
print(greeting(1))

Как и ожидалось, это не работает в Python 2:

  File "test.py", line 1
    def greeting(name: str) -> str:
                     ^
SyntaxError: invalid syntax

Однако это работает для Python 3:

Hello Martin
Traceback (most recent call last):
  File "test.py", line 5, in <module>
    print(greeting(1))
  File "test.py", line 2, in greeting
    return 'Hello ' + name
TypeError: Can't convert 'int' object to str implicitly

Это было неожиданно. На самом деле он еще не проверяет типы, как вы можете видеть на следующем примере (он запускается, но не генерирует исключение):

def greeting(name: str) -> int:
    return 'Hello ' + name

print(greeting('Martin'))

Кажется, что после : должно быть имя функции, но функция, похоже, игнорируется:

def aha(something):
    print("aha")
    return something+"!"

def greeting(name: aha, foo) -> int:
    return 'Hello ' + name + foo

print(greeting('Martin', 'ad'))

То же самое верно и для имени после ->.

Использует ли этот синтаксис подсказки типа что-то еще (например, язык моделирования Java использует комментарии)? Когда этот синтаксис появился в Python? Есть ли способ сделать статическую проверку типов уже с этим синтаксисом? Всегда ли это нарушает совместимость с Python 2?


person Martin Thoma    schedule 21.04.2015    source источник


Ответы (1)


Здесь нет намека на тип. Все, что вы сделали, это предоставили аннотации; они были введены с PEP 3107 (только в Python 3, в Python 2 это не поддерживается). ); они позволяют аннотировать аргументы и возвращаемые значения произвольной информацией для последующей проверки:

>>> greeting.__annotations__
{'name': <class 'str'>, 'return': <class 'str'>}

В остальном здесь вообще не консультируются. Вместо этого вы получили сообщение об ошибке из-за попытки объединить строковые и целочисленные значения в теле функции:

>>> 'Hello ' + 1
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Can't convert 'int' object to str implicitly

Это ошибка пользовательского типа, предназначенная для предоставления дополнительной информации о том, почему конкатенация str + int не удалась; он вызывается методом str.__add__ для любого типа, отличного от str:

>>> ''.__add__(1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Can't convert 'int' object to str implicitly
>>> ''.__add__(True)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Can't convert 'bool' object to str implicitly

Затем PEP 484 предлагает использовать эти аннотации для фактической проверки статического типа с помощью дополнительных инструментов, но, как говорится во введении PEP:

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

Акцент в оригинале.

PEP был вдохновлен существующими инструментами, использующими аннотации PEP 3107; в частности, проект mypy (который возвращается обратно, приняв PEP 484), а также поддержка подсказок в PyCharm IDE и проект pytypedecl. См. оригинальное электронное письмо Гвидо ван Россума, посвященное началу этой работы, а также дополнительное электронное письмо.

mypy, по-видимому, поддерживает Python 2, предварительно обрабатывая аннотации, удаляя их перед компиляцией исходного кода для вас, но в противном случае вы не можете нормально использовать синтаксис кода Python, предназначенный для работы в Python 2.

PEP 484 также описывает использование файлов-заглушек, которые располагаются рядом с обычным файлом Python. файлы; они используют расширение .pyi и содержат только подписи (с подсказками типа), оставляя аннотации основных файлов .py свободными и, таким образом, пригодными для использования на Python 2 (при условии, что вы написали код Polyglot Python иначе).

person Martijn Pieters    schedule 21.04.2015
comment
Знаете ли вы инструменты, которые используют это для проверки типов? - person Martin Thoma; 21.04.2015
comment
@moose: PyCharm также поддерживает синтаксис аннотаций, см. jetbrains.com /pycharm/help/type-hinting-in-pycharm.html - person Martijn Pieters; 21.04.2015
comment
@moose: и третий инструмент, использующий аннотации для подсказок статического типа: github.com/google/pytypedecl - person Martijn Pieters; 21.04.2015
comment
@MartijnPieters интересно, я не знал об этом - person jonrsharpe; 21.04.2015