Аннотации типов PEP-484 с собственными типами

PEP-484 предоставляет семантику для аннотаций типов. Они очень ориентированы на а) документацию и б) помощь для IDE. Они меньше ориентированы на оптимизацию кода.

Например, к сожалению, невозможно использовать аннотации PEP 484 с Cython https://groups.google.com/d/msg/cython-users/DHcbk78rDec/6-b5XtCRGBEJ

или с Numba, последний использует свой собственный формат аннотации в виде строк, например "float64 (int32, int32)" http://numba.pydata.org/numba-doc/0.24.0/reference/types.html.

Как мне работать в рамках PEP 484 с моими собственными типами? Я явно не хочу нарушать семантику PEP-484, но хочу дополнить существующие типы дополнительной информацией, видимой моей собственной проверке типов, но невидимый для любого средства проверки типов или IDE, совместимого с PEP-484.

Будет ли следующее интерпретироваться в семантике PEP-484 как List [int]?

class Int32(int): pass
x = [1]   # type: List[Int32]

Как насчет более модного шрифта, подобного этому?

def combine(typeA, typeB):
    class X(typeA, typeB): pass
    return X

class Metre(): pass

# is y an 'int' to PEP-484 typecheckers?
y = 1 # type: combine(Int32, Metre)

Какие-либо рекомендации для библиотек по работе с подсказками типов как для синтаксического анализа, так и для проверки типов?


person Dan    schedule 24.06.2016    source источник
comment
Аналогичный вопрос по numpy и 484 - stackoverflow.com/q/35673895/901925   -  person hpaulj    schedule 24.06.2016
comment
Мне интересно изучать системы разных типов. Я хотел бы иметь систему с гибкостью Шена (shenlanguage.org/learn -shen / types / types_sequent_calculus.html) и возможность определять собственные типы и правила ввода. Первым шагом является создание статической программы проверки единиц измерения. Семантика набора 484 очень заманчива, b / c они очень гибкие, например, я (надеюсь) выразить, что переменная имеет тип Int32 и в то же время имеет измеритель размера. Оптимизатору нравится int32, проверяются физические единицы, и графический интерфейс распознает y как int.   -  person Dan    schedule 24.06.2016
comment
хорошая ссылка на большой вопрос, который идет в правильном долгосрочном направлении, мне также нравится проект datashape. Для начала меня больше интересует типизация, как обрабатывать мои собственные типы в контексте 484 и как анализировать информацию о типах из программы. Конечно, я надеюсь, что в будущем внешние библиотеки смогут в максимальной степени обмениваться аннотациями типов.   -  person Dan    schedule 24.06.2016


Ответы (1)


Начиная с Python 3.5, у нас есть не только PEP 483, PEP 484, но также _ 1_ модуль, реализующий его.

Для полного понимания вы можете прочитать эти 3 документа. Но для вашего конкретного случая краткий ответ заключается в том, что в области PEP484 вы можете работать с собственными типами 4 способами:

  1. просто комментируйте, используя собственные типы,
  2. создать псевдонимы типов,
  3. используйте NewType или
  4. использовать собственные общие типы

Если то, что вы ищете, превыше всего:

дополнительная информация, видимая моей собственной программе проверки типов, но невидимая для любой программы проверки типов, соответствующей PEP-484

то второй подход дает вам именно это. Если вы это сделаете:

Int32 = int
Int64 = int

x = 0 # type: Int32
y = 0 # type: Int64

Тогда Int32 и Int64 будут одинаковыми в области PEP484, но вы можете добавить некоторые дополнительные проверки, просмотрев AST (абстрактное синтаксическое дерево) вашего кода, используя поддерживаемый сообществом _ 6_ модуль. Этот модуль анализирует комментарии типов в дополнение к коду, поэтому вы можете прочитать используемую точную аннотацию и, таким образом, получить некоторую дополнительную информацию о типах для x и y.


И, если быть невидимым не является приоритетом номер один, тогда:

  • вместо class Int32(int): pass я бы предпочел typing.NewType('Int32', int), и

  • вместо combine(Int32, Metre) я бы использовал typing.Union[Int32, Metre].

i.e.

Int32 = typing.NewType('Int32', int)

class Metre:
    pass

x = [Int32(1)]  # type: List[Int32]
y = Int32(1) # type: typing.Union[Int32, Metre]

print(x[0] + 1) # ok, since Int32 is still int
y = Metre() # ok, since y can be Int32 or Metre

В приведенном выше коде вы можете запустить поддерживаемую сообществом статическую проверку типов mypy.


И typed-ast, и _ 16_ сейчас (2016 год) очень активно разрабатываются. Не все работает так, как ожидалось, но, насколько я вижу, они уже достаточно хороши для многих случаев использования, и, похоже, альтернатив нет.

person mbdevpl    schedule 03.10.2016