首页 > 解决方案 > 绕过“typing.Union 不是泛型类”

问题描述

在 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

这将是用或SetOrDict定义的情况。(至少在 Python 3.7 中。)typing.Uniontyping.TypeVar

看起来有一种方法可以进行子类化Generic,大概像:

class SetOrDict(typing.Generic[StrOrURL]):
    # ...

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

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

标签: pythonpython-3.xtype-hinting

解决方案


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

你有一个新的工会:

URLorStrSetOrDict = typing.Union[Set[StrOrUrl], Dict[StrOrUrl, Any]]

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

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


推荐阅读