从类型输入中提取数据

时间:2018-07-04 10:51:15

标签: python python-3.x generics instanceof typing

除了在类型提示方面,我在使用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

documentation对此也没有帮助。同样,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 :(得分:1)

检查变量是否符合键入对象

要检查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