Существует ли каноническая реализация «isinstance» для типов ввода? - PullRequest
0 голосов
/ 02 апреля 2020

Вы не можете использовать печатать типы, такие как Dict[str, int] в проверке isinstance:

Python 3.7.6 (default, Dec 30 2019, 19:38:28)
Type 'copyright', 'credits' or 'license' for more information
IPython 7.12.0 -- An enhanced Interactive Python. Type '?' for help.

In [1]: from typing import Dict

In [2]: myvar = {"a": 1}

In [3]: isinstance(myvar, Dict[str, int])
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-3-a8fee57141ae> in <module>
----> 1 isinstance(myvar, Dict[str, int])

Однако любая библиотека, которая выполняет проверку типов, должна иметь возможность выполнять что-то вроде isinstance(myvar, Dict[str, int]) (... я понимаю, что это следует называть чем-то отличным от isinstance, что это не совсем то же самое)

Я чувствую, что эквивалентная функция, которая работает для набора текста, должна существует где-то, может быть, в mypy проекте? (но там много сложного кода, и я пока не могу его найти)

Есть множество проектов, кроме mypy, которые нуждаются в этом, такие библиотеки, как pydanti c для Например, и AFAICT, они все имеют сложную ручную реализацию, и кажется, что существует множество крайних случаев (или просто ... «случаев»), которые необходимо перечислить и охватить. Это приводит к ошибкам / ограниченному распознаванию типов, например https://github.com/bloomberg/attrs-strict/issues/27

Кажется, что существует потребность в канонической реализации этой функциональности. Кто-то уже существует где-то, чего я не нашел?

Я приведу мотивирующий пример из Python stdlib:

https://docs.python.org/3/library/functools.html#functools. singledispatch

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

>>> @fun.register
... def _(arg: int, verbose=False):
...     if verbose:
...         print("Strength in numbers, eh?", end=" ")
...     print(arg)
...
>>> @fun.register
... def _(arg: list, verbose=False):
...     if verbose:
...         print("Enumerate this:")
...     for i, elem in enumerate(arg):
...         print(i, elem)

Что ж, это круто. Но это обман, потому что в наши дни мы обычно не аннотируем вторую функцию, используя встроенную list, а скорее что-то вроде List[str] ... и это не работает, потому что singledispatch просто делает наивный isinstance проверить, и это не может справиться с наборами дженериков. Так что singledispatch на самом деле не поддерживает отправку по аннотации типа, как это утверждается.

1 Ответ

1 голос
/ 02 апреля 2020

Нет, канонической проверки такого рода не существует. Как говорит комментатор, типизация была введена для stati c проверок типов, и я думаю, что многие разработчики ядра считают, что она должна оставаться такой.

Ближайшая вещь, о которой я могу думать, это pydanti c ' с parse_obj_as. Он отличается тем, что пытается привести объект к указанному типу c и в случае сбоя выдает ошибку, но довольно близко.

Использование:

from pydantic import parse_obj_as
from typing import Dict

parse_obj_as(Dict[str, int], {'xxx': 1, 'yyy': 2})
#> {'xxx': 1, 'yyy': 2}

parse_obj_as(Dict[str, int], {'xxx': 1, 123: '12'})
#> {'xxx': 1, '123': 12}

parse_obj_as(Dict[str, int], ['not a dict'])
#> ValidationError: 1 validation error for ParsingModel[Dict[str, int]]
#> __root__
#>   value is not a valid dict (type=type_error.dict)

Документы здесь .

Примечание: я строю пиданти c, поэтому я немного пристрастен.

...