extracting data from typing types

微笑、不失礼 提交于 2020-01-22 19:10:48

问题


I am having some issues working with the typing types in Python for any more than type hinting:

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

Now I would like to

  1. Check if string_list conforms to string_list_class.
  2. Check if string_list_class is a list.
  3. If so, check the class, that string_list_class is a list of.

I find myself unable to achieve any of those:

>>> 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

The documentation also is not really helpful with that. Also the API does not seem to be intended to be used that way, however, I need to use that functionality.

Bodging around

A way I found to answer 2. is, that

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

Tough I have no access to _GenericAlias I can build it myself:

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

However that does not seem like a good solution at all and it also yields True for other classes like Collection.

For 1. and 3. I could imagine hacking something together with repr(type(string_list)) and repr(string_list_class) and somehow comparing that string to something, but that also is not a good solution.

But there must be a better way to do this


回答1:


Checking if a variable conforms to a typing object

To check if string_list conforms to string_list_class, you can use the typeguard type checking library.

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")

Checking the generic type of a typing object

To check if string_list_class is a list type, you can use the typing_inspect library:

from typing_inspect import get_origin
from typing import List

get_origin(List[str]) # -> List

You could also use the private __origin__ field, but there is no stability guarantee for it.

List[str].__origin__ # -> list

Checking the type argument of a typing object

To check the class, that string_list_class is a list of, you can use the typing_inspect library again.

from typing_inspect import get_parameters
from typing import List

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

As before, there is also a private field you can use if you like to take risks

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


来源:https://stackoverflow.com/questions/51171908/extracting-data-from-typing-types

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!