Объекты 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,)