Объекты GenericAlias (добавлен в Python 3.9.) создаются путем подписки на класс (обычно контейнер), например list[int]. Они предназначены в первую очередь для аннотаций типов.
Обычно подписка на объекты-контейнеры вызывает метод объекта __getitem__(). Подписка на классы некоторых контейнеров может вместо этого метода вызывать метод класса __class_getitem__(). Метод класса __class_getitem__() должен возвращать объект универсального псевдонима GenericAlias.
_Примечание_. Если присутствует метод метакласса класса __getitem__(), то он будет иметь приоритет над методом __class_getitem__(), определенным в классе.
Объект GenericAlias действует как прокси для универсальных типов, реализуя параметризованные универсальные шаблоны - конкретный универсальный экземпляр, который предоставляет типы для элементов контейнера.
Доступ к пользовательскому типу для объекта GenericAlias можно получить из types.GenericAlias и использовать для проверок isinstance(). Его также можно использовать для непосредственного создания объектов GenericAlias.
T[X, Y, ...]Создает GenericAlias - обобщенное представление, которое представляет тип T, содержащий элементы типов X, Y и других в зависимости от используемого T.
Например, функция ожидает список, содержащий элементы с float:
def average(values: list[float]) -> float: return sum(values) / len(values)
Другой пример сопоставления объектов с использованием словаря dict, который является универсальным типом, ожидающим двух параметров типа, представляющих тип ключа key и тип значения value.
В этом примере функция ожидает dict с ключами типа str и значениями типа int:
def send_post_request(url: str, body: dict[str, int]) -> None: ...
Новое в Python 3.9.
GenericAlias;GenericAlias.GenericAlias.Встроенные функции isinstance() и issubclass() не принимают типы GenericAlias в качестве второго аргумента:
>>> isinstance([1, 2], list[str]) # Traceback (most recent call last): # File "<stdin>", line 1, in <module> # TypeError: isinstance() argument 2 cannot be a parameterized generic
Среда выполнения Python не применяет аннотации типов. Это распространяется на универсальные типы и их параметры типа. При создании объекта из GenericAlias элементы контейнера не проверяются на соответствие их типу.
Например, следующий код не рекомендуется к использованию, но он будет работать без ошибок:
>>> t = list[str] >>> t([1, 2, 3]) # [1, 2, 3]
Кроме того, параметризованные универсальные шаблоны стирают параметры типа во время создания объекта:
>>> t = list[str] >>> type(t) # <class 'types.GenericAlias'> >>> l = t() >>> type(l) # <class 'list'>
Вызов функций repr() или str() для универсального типа показывает параметризованный тип:
>>> repr(list[int]) # 'list[int]' >>> str(list[int]) # 'list[int]'
Метод дженериков __getitem__() вызовет исключение, во избежание таких ошибок, как dict[str][str]:
>>> dict[str][str] # Traceback (most recent call last): # File "<stdin>", line 1, in <module> # TypeError: There are no type variables left in dict[str]
Однако такие выражения действительны при использовании типов переменных. В индексе должно быть столько элементов, сколько есть элементов типов переменных в __args__ объекта GenericAlias.
>>> from typing import TypeVar >>> Y = TypeVar('Y') >>> dict[str, Y][int] dict[str, int]
tuple,list,dict,set,frozenset,type,collections.deque,collections.defaultdict,collections.OrderedDict,collections.Counter,collections.ChainMap,collections.abc.Awaitable,collections.abc.Coroutine,collections.abc.AsyncIterable,collections.abc.AsyncIterator,collections.abc.AsyncGenerator,collections.abc.Iterable,collections.abc.Iterator,collections.abc.Generator,collections.abc.Reversible,collections.abc.Container,collections.abc.Collection,collections.abc.Callable,collections.abc.Set,collections.abc.MutableSet,collections.abc.Mapping,collections.abc.MutableMapping,collections.abc.Sequence,collections.abc.MutableSequence,collections.abc.ByteString,collections.abc.MappingView,collections.abc.KeysView,collections.abc.ItemsView,collections.abc.ValuesView,contextlib.AbstractContextManager,contextlib.AbstractAsyncContextManager,re.Pattern,re.Match.Все параметризованные универсальные шаблоны реализуют специальные атрибуты, доступные только для чтения.
genericalias.__origin__:Этот атрибут указывает на непараметрический универсальный класс:
>>> list[int].__origin__ # <class 'list'>
genericalias.__args__:Этот атрибут представляет собой кортеж универсальных типов (возможно, длиной 1), переданный исходному методу __class_getitem__() универсального контейнера:
>>> dict[str, list[int]].__args__ # (<class 'str'>, list[int])
genericalias.__parameters__:Этот атрибут представляет собой лениво вычисляемый кортеж (возможно, пустой) переменных уникального типа, найденных в __args__:
>>> from typing import TypeVar >>> T = TypeVar('T') >>> list[T].__parameters__ # (~T,)