【问题标题】:How do I define a `typing.Union` dynamically?如何动态定义`typing.Union`?
【发布时间】:2020-07-15 16:14:47
【问题描述】:

我在几个 if 项目中使用 Typeguard 在 Python 运行时进行类型检查。效果很好。

我遇到过这样一种情况,函数参数的类型是由几个动态收集的数据类型组成的typing.Union。例如

def find_datatypes():
    # some stuff ...
    return (str, int) # dynamically generated list / tuple

datatypes = find_datatypes()

现在我想从datatypes 生成一个typing.Union 以供最终在函数中使用。我希望解包语法能够工作:

my_union = typing.Union[*datatypes]

@typeguard.typechecked
def some_function(param: my_union):
    pass

但是,它没有:

    my_union = typing.Union[*datatypes]
                            ^
SyntaxError: invalid syntax

我将如何实现我想要的?

【问题讨论】:

  • 仅供参考,解包语法不起作用,因为这是 __getitem__ 语法,[...],而不是 __call__ 语法,(...)
  • Python 类型注解的设计几乎完全围绕静态用例。不太支持动态地执行任何事情
  • @jonrsharpe 是啊...__getitem__毕竟是一个函数,所以我想为什么不试试。通常,由于其令人难以置信的一致性,像这样奇怪的东西只适用于 Python。
  • @user2357112supportsMonica 是的,这也是“手册”所说的。相反,可以在运行时使用它们,这就是 Typeguard 存在的原因。知道如何使这个工作吗?

标签: python type-hinting python-typing dynamic-typing


【解决方案1】:

你可以这样做:

my_union = typing.Union[datatypes]

在运行时,thing[x, y] 已经等同于 thing[(x, y)]

也就是说,要记住一些限制。特别是,当使用字符串注解(将在某个时候成为默认值 - 目前计划用于 Python 3.11)时,my_union 必须在 some_function 的全局命名空间中为 typeguard 或其他任何东西可用在运行时解析注释。这限制了很多闭包用例,以及很多动态添加注释的尝试。

另外,如您所料,mypy 不会认为这些都是有效的。

【讨论】:

  • 呵呵,__future__ 库的文档应该更新了。它仍然说annotations 在版本 4 中成为强制性的。我不确定 PEP 563 何时更新为 Python 3.10(或者它总是说 Python 3.10?)
  • @chepner:我很确定 PEP 563 曾经说过 4.0。关于tracker 的讨论看起来他们正在努力在 3.10 之前将其加入。
猜你喜欢
  • 2012-03-27
  • 2011-04-10
  • 2021-10-04
  • 1970-01-01
  • 1970-01-01
  • 2022-10-25
  • 2019-03-26
  • 2015-07-08
  • 1970-01-01
相关资源
最近更新 更多