Обойти "typing.Union не является универсальным классом" - PullRequest
0 голосов
/ 08 января 2019

В модуле 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 определено с typing.Union или typing.TypeVar. (По крайней мере, в Python 3.7.)

Похоже, есть способ подкласса Generic, предположительно такой:

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

Но это немедленно поднимет TypeError: Parameters to Generic[...] must all be type variables.

Есть ли способ приспособиться к вышесказанному? Т.е., какова рекомендуемая практика для подписки пользовательских (неуниверсальных) typedefs?

1 Ответ

0 голосов
/ 08 января 2019

Вы не можете использовать Union[...], псевдоним или другое, как универсальный тип, нет. Ваше объединение содержимое также не является общим, вы не можете указать, какие типы объектов dict или set могут содержать, используя dict или set напрямую, вы бы использовали Set или Dict.

У вас новый союз:

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

Обратите внимание, что в словаре есть ключи и значения , вам необходимо предоставить информацию об обоих. Если это используется в качестве входных данных для API, рассмотрите возможность использования более общих и неизменных типов AbstractSet и Mapping; это дает понять, что вашему API нужно только прочитать информацию.

Лично я бы усердно занимался рефакторингом кодовой базы, которая настолько грязна из-за того, какие типы объектов она может принимать. Требование, чтобы API принимал только наборы и существующий код должен передавать set(dictionary) вместо dictionary, не является трудным требованием, или, возможно, API действительно будет работать с любым повторяемым из StrOrUrl.

...