Skip to content
Advertisement

What’s the correct way to check if an object is a typing.Generic?

I’m trying to write code that validates type hints, and in order to do so I have to find out what kind of object the annotation is. For example, consider this snippet that’s supposed to tell the user what kind of value is expected:

import typing

typ = typing.Union[int, str]

if issubclass(typ, typing.Union):
    print('value type should be one of', typ.__args__)
elif issubclass(typ, typing.Generic):
    print('value type should be a structure of', typ.__args__[0])
else:
    print('value type should be', typ)

This should print “value type should be one of (int, str)”, but instead it throws an exception:

Traceback (most recent call last):
  File "untitled.py", line 6, in <module>
    if issubclass(typ, typing.Union):
  File "C:Python34libsite-packagestyping.py", line 829, in __subclasscheck__
    raise TypeError("Unions cannot be used with issubclass().")
TypeError: Unions cannot be used with issubclass().

isinstance doesn’t work either:

>>> isinstance(typ, typing.Union)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:Python34libsite-packagestyping.py", line 826, in __instancecheck__
    raise TypeError("Unions cannot be used with isinstance().")
TypeError: Unions cannot be used with isinstance().

What’s the correct way to check if typ is a typing.Generic?

If possible, I would like to see a solution that’s backed by documentation or a PEP or some other resource. A “solution” that “works” by accessing undocumented, internal attributes is easy to find. But more likely than not, it’ll turn out to be an implementation detail and will change in future versions. I’m looking for “the right way” to do it.

Advertisement

Answer

As pointed out by sonny-garcia in the comments, get_origin() works from python 3.8

import typing
from typing import get_origin

typ = typing.Union[int, str]
get_origin(typ) == typing.Union
#True

You can find more details in the docs

User contributions licensed under: CC BY-SA
8 People found this is helpful
Advertisement