如何动态定义 `typing.Union`?

How do I define a `typing.Union` dynamically?

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

我遇到过函数参数的类型是由一些动态收集的数据类型组成的 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

我怎样才能实现我想要的?

你可以这样做:

my_union = typing.Union[datatypes]

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

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

此外,如您所料,mypy 不会认为这些有效。