Check a variable against Union type at runtime in Python 3.6
In Python 3.8 and later, the approach suggested by MSeifert and Richard Xia can be improved by not using the undocumented attributes __origin__
and __args__
. This functionality is provided by the new functions typing.get_args(tp)
and typing.get_origin(tp)
:
>> from typing import Union, get_origin, get_args>> x = Union[int, str]>> get_origin(x), get_args(x)(typing.Union, (<class 'int'>, <class 'str'>))>> get_origin(x) is UnionTrue>> isinstance(3, get_args(x))True>> isinstance('a', get_args(x))True>> isinstance([], get_args(x))False
P.S.: I know that the question is about Python 3.6 (probably because this was the newest version at the time), but I arrived here when I searched for a solution as a Python 3.8 user. I guess that others might be in the same situation, so I thought that adding a new answer here makes sense.
You could use the __args__
attribute of Union
which holds a tuple
of the "possible contents:
>>> from typing import Union>>> x = Union[int, str]>>> x.__args__(int, str)>>> isinstance(3, x.__args__)True>>> isinstance('a', x.__args__)True
The __args__
argument is not documented so it could be considered "messing with implementation details" but it seems like a better way than parsing the repr
.
The existing accepted answer by MSeifert (https://stackoverflow.com/a/45959000/7433423) does not distinguish Union
s from other generic types, and it is difficult to determine at runtime whether a type annotation is a Union
or some other generic type like Mapping
due to the behavior of isinstance()
and issubclass()
on parameterized Union
types.
It appears that generic types will have an undocumented __origin__
attribute which will contain a reference to the original generic type used to create it. Once you have confirmed that the type annotation is a parameterized Union
, you can then use the also undocumented __args__
attribute to get the type parameters.
>>> from typing import Union>>> type_anno = Union[int, str]>>> type_anno.__origin__ is UnionTrue>>> isinstance(3, type_anno.__args__)True>>> isinstance('a', type_anno.__args__)True