Как я могу использовать номинальный набор текста в mypy?

Это не мой точный вариант использования, но он похож. Предположим, я хочу определить две аннотации ввода:

Matrix = np.ndarray
Vector = np.ndarray

Теперь я хочу, чтобы потенциальный контролер типов пожаловался, когда я передаю Matrix функции, которая принимает Vector:

def f(x: Vector):
    ...

m: Matrix = ...
f(m)  # Bad!

Как отметить эти типы как несовместимые?


person Neil G    schedule 21.06.2019    source источник
comment
Какую проверку типов вы используете? Похоже, что тот, который вы используете, использует структурную типизацию, где вам нужна номинальная типизация.   -  person jhpratt    schedule 22.06.2019
comment
@jhpratt: Я сейчас не использую никаких средств проверки типов. Я скоро изучу варианты. Я неукоснительно использую аннотации типов, и пока у меня около 350 аннотаций. Хотелось бы сделать это правильно с первого раза. Я не знаю, что такое структурная и номинальная типизация.   -  person Neil G    schedule 22.06.2019
comment
Может, тогда попробуем средство проверки типов и посмотрим, работает ли оно вообще? Я не вижу проблемы прямо сейчас, если вы этого еще не сделали. Структурный заботится о форме данных, номинальный заботится об имени типа (по сути).   -  person jhpratt    schedule 22.06.2019
comment
@jhpratt mypy не жалуется, но я нашел ответ на свой вопрос. В любом случае спасибо, что заглянули.   -  person Neil G    schedule 22.06.2019
comment
Выглядит неплохо! Я просто смотрел документацию mypy, и в ней упоминалось, что она поддерживает номинальную (это то, что вы хотели). Хорошая находка.   -  person jhpratt    schedule 22.06.2019
comment
Как отличить вектор от матрицы? В numpy также нет встроенной категории. И, как вы заметили, в numpy нет фреймворка для набора текста.   -  person hpaulj    schedule 22.06.2019
comment
@hpaulj В моем коде есть два типа матриц (различающиеся тем, что они представляют), и я хочу, чтобы они оставались отдельными, и я хочу, чтобы система набора текста проверила это. Я мог бы вместо этого сказать PolarVector и CartesianVector.   -  person Neil G    schedule 22.06.2019


Ответы (1)


Похоже, что я могу использовать typing.NewType для создания отдельных типов:

from typing import NewType


A = NewType('A', int)
B = NewType('B', int)

def f(a: A):
    pass

b: B
f(b)

дает

a.py:11: error: Argument 1 to "f" has incompatible type "B"; expected "A"

К сожалению, это не работает с np.ndarray, пока либо numpy не реализует подсказку типа, либо NewType не поддерживает базовый тип Any.

person Neil G    schedule 21.06.2019
comment
Какие? Почему бы не работать с numpy.ndarray? Можете ли вы показать пример отказа NewType с numpy.ndarray? - person user2357112 supports Monica; 22.06.2019
comment
@ user2357112 Замени int на np.ndarray и запустите через mypy. - person Neil G; 22.06.2019
comment
Блех, верно, mypy слишком сильно полагается на файлы-заглушки. Он даже не знает, что такое numpy.ndarray. - person user2357112 supports Monica; 22.06.2019
comment
@ user2357112 Да, это тоже исправит: github.com/python/mypy/ issues / 6701 # issuecomment-485037387 Надеюсь, это скоро будет реализовано. - person Neil G; 22.06.2019