在 Python 3.5.2 中解压 Optional 类型注解

Unpack Optional type annotation in Python 3.5.2

给出这个例子:

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] 等注释中获取 class,然后使用 T:

annot = typing.Optional[T]
cls = # MAGIC?!
assert cls is T

在这些情况下,我更愿意简单地参考实现。在 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

这表明 class 存储在 __union_params__ 属性中:

typing.get_type_hints(foo)['bar'].__union_params__[0] is T

然而,在 3.5.3 的 the commit 5fc25a873cfdec27e46f71e62c9b65df5667c1b4 中,这已更改为 __args__

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.63.7)。

这是由于打字模块的临时状态。内部 API 的许多方面在微版本之间发生了变化,因此您可能不得不处理许多晦涩的变化。