给出这个例子:
import typing
def foo(bar: int = None):
pass
typing.get_type_hints(foo)
bar
的类型提示为typing.Union[int, None]
。如何从中获取int
? __args__
和__parameters__
属性似乎都不适用于Python 3.5.2。
更具体地说,我正在尝试编写一个通用装饰器来检查函数的签名并对参数执行特定的操作。为此,它需要从Optional[T]
等注释中获取类,然后使用T
:
annot = typing.Optional[T]
cls = # MAGIC?!
assert cls is T
答案 0 :(得分:4)
在3.5.2
中,要获取Union
的参数,您必须使用__union_params__
。
>>> from typing import Union
>>> d = Union[int, str]
>>> print(*d.__union_params__)
<class 'int'> <class 'str'>
不幸的是,这似乎仅适用于3.5.2
,它已在3.5.3
中更改为使用__args__
:
>>> from typing import Union
>>> t = Union[int, str]
>>> t.__union_params__
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: '_Union' object has no attribute '__union_params__'
>>> print(*t.__args__)
<class 'int'> <class 'str'>
并在以后的版本__args__
和3.6
中停留了3.7
。
这是由于输入模块的临时状态。内部API的许多方面都在微版本之间发生变化,因此您可能不得不处理许多模糊的更改。
答案 1 :(得分:2)
在这些情况下,我更愿意参考实施。在3.5.2中,这是__repr__
of Union
:
def __repr__(self):
r = super().__repr__()
if self.__union_params__:
r += '[%s]' % (', '.join(_type_repr(t)
for t in self.__union_params__))
return r
这表明该类存储在__union_params__
属性中:
typing.get_type_hints(foo)['bar'].__union_params__[0] is T
然而,对于3.5.3,这已更改为the commit 5fc25a873cfdec27e46f71e62c9b65df5667c1b4
中的__args__
。