32

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

7
  • I get point 1, but what's the purpose of point 2? If string_list conforms to string_list_class, then you already know that it's a list. And I have no idea what point 3 is supposed to mean. Commented Jul 4, 2018 at 10:59
  • I want to check if string_list_class is a List type in general. It might be a list of str, int, MyObject or something else. This is unrelated to 1. With 3 I want to extract MyObject from List[MyObject]. Commented Jul 4, 2018 at 11:01
  • 1
    Ok, I see. But... I'm not sure if it's a good idea to ask 3 mostly unrelated questions at the same time... Commented Jul 4, 2018 at 11:12
  • I agree, but they are not entirely unrelated IMHO, and answers to one or two of those questions could answer the others. I was unable to find a solution, but if there is one, the same source probably also could answer the other questions. Commented Jul 4, 2018 at 11:15
  • 1
    For point 3, see How to access the type arguments of typing.Generic?. And What's the correct way to check if an object is a typing.Generic? might help with point 2. Commented Jul 4, 2018 at 11:20

1 Answer 1

30

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 
Sign up to request clarification or add additional context in comments.

3 Comments

Worth noting that a lot of the functionality in typing_inspect doesn't work in python 3.9. Unfortunately it seems that doing runtime checks for generic types can be a bit unreliable
yeah I'm in python 3.10.13, and get_parameters(List[str]) returns (), but get_origin(List[str]) does return list

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.