解压缩Python 3.5.2中的可选类型注释

时间:2017-09-13 12:53:20

标签: python python-3.x annotations typing

给出这个例子:

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

2 个答案:

答案 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__