绕过“typing.Union 不是泛型类”

Bra*_*mon 6 python type-hinting python-3.x

在Python的typing模块中,似乎任何不是泛型类型的东西都不支持下标:

>>> import typing
>>> from yarl import URL

>>> StrOrURL = typing.Union[URL, str]
>>> typing.List[StrOrURL]                # OK; List is generic
typing.List[typing.Union[yarl.URL, str]]

>>> SetOrDict = typing.Union[set, dict]
>>> SetOrDict[StrOrURL]                  # Raises
TypeError: typing.Union[set, dict] is not a generic class
Run Code Online (Sandbox Code Playgroud)

无论是用或SetOrDict定义,情况都是如此。(至少在 Python 3.7 中是这样。)typing.Uniontyping.TypeVar

看起来有一种方法可以子类化Generic,大概是这样的:

class SetOrDict(typing.Generic[StrOrURL]):
    # ...
Run Code Online (Sandbox Code Playgroud)

但这会立即引发TypeError: Parameters to Generic[...] must all be type variables

有没有办法适应以上情况呢?即,下标用户定义(非通用)typedef 的推荐做法是什么?

Mar*_*ers 3

您不能使用Union[...]、别名或其他方式作为泛型类型,不行。您的联合内容也不是通用的,您无法直接使用or来说明 adictsetobject 可以包含哪些类型,您可以使用or 。dictsetSetDict

您有一个新工会:

URLorStrSetOrDict = typing.Union[Set[StrOrUrl], Dict[StrOrUrl, Any]]
Run Code Online (Sandbox Code Playgroud)

请注意,字典具有键和值,您需要提供两者的信息。如果将其用作 API 的输入,则考虑使用更通用且不可变的AbstractSet类型Mapping;这清楚地表明您的 API 只需要读取信息。

就我个人而言,我会努力重构一个关于它可以接受什么类型的对象的代码库。要求 API 只接受集合并且必须传入现有代码set(dictionary)并不是dictionary一个艰巨的要求,或者 API 可能真的可以与任何可迭代StrOrUrl.