извлечение данных из типов ввода - PullRequest
0 голосов
/ 04 июля 2018

У меня возникли некоторые проблемы при работе с типами typing в Python, кроме случаев подсказки типов:

>>> from typing import List
>>> string_list = ['nobody', 'expects', 'the', 'spanish', 'inqusition']
>>> string_list_class = List[str]

Теперь я бы хотел

  1. Проверьте, соответствует ли string_list string_list_class.
  2. Проверьте, является ли string_list_class списком.
  3. Если это так, проверьте класс, что string_list_class является списком.

Я не могу достичь ни одного из них:

>>> isinstance(string_list, string_list_class)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/typing.py", line 708, in __instancecheck__
    return self.__subclasscheck__(type(obj))
  File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/typing.py", line 716, in __subclasscheck__
    raise TypeError("Subscripted generics cannot be used with"
TypeError: Subscripted generics cannot be used with class and instance checks

>>> issubclass(string_list_class, List)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/typing.py", line 716, in __subclasscheck__
    raise TypeError("Subscripted generics cannot be used with"
TypeError: Subscripted generics cannot be used with class and instance checks

Документация также не очень помогает в этом. Кроме того, API, похоже, не предназначен для использования таким образом, однако мне нужно использовать эту функциональность .

Жужжание

Я нашел способ ответить 2.

>>> type(string_list_class)
<class 'typing._GenericAlias'>

Хотя у меня нет доступа к _GenericAlias Я могу построить его сам:

>>> _GenericAlias = type(List[str])
>>> isinstance(string_list_class, _GenericAlias)
True

Однако это совсем не похоже на хорошее решение, а также дает True для других классов, таких как Collection.

Для 1. и 3. Я мог бы представить, что можно что-то взломать вместе с repr(type(string_list)) и repr(string_list_class) и как-то сравнить эту строку с чем-то, но это тоже не очень хорошее решение.

Но должен быть лучший способ сделать это

1 Ответ

0 голосов
/ 15 мая 2019

Проверка соответствия переменной типизирующему объекту

Чтобы проверить, соответствует ли string_list string_list_class, вы можете использовать библиотеку проверки типа typeguard .

from typeguard import check_type

try:
    check_type('string_list', string_list, string_list_class)
    print("string_list conforms to string_list_class")
except TypeError:
    print("string_list does not conform to string_list_class")

Проверка универсального типа печатного объекта

Чтобы проверить, является ли string_list_class типом списка, вы можете использовать библиотеку typing_inspect :

from typing_inspect import get_origin
from typing import List

get_origin(List[str]) # -> List

Вы также можете использовать приватное поле __origin__, но для него нет гарантии стабильности.

List[str].__origin__ # -> list

Проверка аргумента типа объекта ввода

Чтобы проверить класс, который string_list_class является списком, вы можете снова использовать библиотеку typing_inspect .

from typing_inspect import get_parameters
from typing import List

assert get_parameters(List[str])[0] == str

Как и раньше, есть также личное поле, которое вы можете использовать, если хотите рисковать

List[str].__args__[0] # -> str
...