在 Python 3.6 中运行时根据 Union 类型检查变量

新手上路,请多包涵

我正在尝试编写一个函数装饰器,它使用 Python 3.6 类型提示来检查参数字典是否遵守类型提示,如果没有引发错误并清楚地描述问题,则用于 HTTP API。

问题是,当函数的参数使用 Union 类型时,我无法在运行时检查变量。

比如我有这个功能

from typing import Union
def bark(myname: str, descr: Union[int, str], mynum: int = 3) -> str:
    return descr + myname * mynum

我可以:

 isinstance('Arnold', bark.__annotations__['myname'])

但不是:

 isinstance(3, bark.__annotations__['descr'])

因为 Union 不能与 isinstanceissubclass 一起使用。

我找不到使用类型对象检查它的方法。我试图自己实施检查,但是 bark.__annotations__['descr'] typing.Union[int, str] 如果不使用丑陋的 hack,我无法在运行时访问类型列表检查 bark.__annotations__['descr'].__repr__()

有没有正确的方法来访问这些信息?还是故意在运行时不易访问?

原文由 Jacopofar 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 452
2 个回答

您可以使用 __args__ 属性 Union 包含 tuple 的“可能内容:

 >>> from typing import Union

>>> x = Union[int, str]
>>> x.__args__
(int, str)
>>> isinstance(3, x.__args__)
True
>>> isinstance('a', x.__args__)
True

__args__ 参数没有记录,所以它可以被认为是“混淆实现细节”,但它似乎是比解析 repr 更好的方法。

原文由 MSeifert 发布,翻译遵循 CC BY-SA 3.0 许可协议

在 Python 3.8 及更高版本中,可以通过不使用未记录的属性 __origin____args__ 来改进 MSeifertRichard Xia 建议的方法。此功能由新函数 typing.get_args(tp)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 Union
True
>> isinstance(3, get_args(x))
True
>> isinstance('a', get_args(x))
True
>> isinstance([], get_args(x))
False

PS:我知道问题是关于Python 3.6的(可能是因为这是当时最新的版本),但是当我以Python 3.8用户的身份搜索解决方案时来到这里。我猜其他人可能处于同样的情况,所以我认为在这里添加一个新的答案是有道理的。

原文由 Frank 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题