diff --git a/docs/reference/generics.rst b/docs/reference/generics.rst index c39d2bc11..0732671b3 100644 --- a/docs/reference/generics.rst +++ b/docs/reference/generics.rst @@ -19,11 +19,7 @@ Here is a very simple generic class that represents a stack: .. code-block:: python - from typing import TypeVar, Generic - - T = TypeVar('T') - - class Stack(Generic[T]): + class Stack[T]: def __init__(self) -> None: # Create an empty list with items of type T self.items: list[T] = [] @@ -37,6 +33,23 @@ Here is a very simple generic class that represents a stack: def empty(self) -> bool: return not self.items +.. note:: + + The type parameter syntax (e.g., ``class Foo[T]:``) is available in Python 3.12 and newer. + For earlier Python versions, generic classes need to be defined using + ``TypeVar`` and ``Generic``, as shown below. + +For compatibility with older Python versions, the same class may be written as: + +.. code-block:: python + + from typing import TypeVar, Generic + + T = TypeVar('T') + + class Stack(Generic[T]): + ... + The ``Stack`` class can be used to represent a stack of any type: ``Stack[int]``, ``Stack[tuple[int, str]]``, etc. @@ -56,7 +69,7 @@ construction of the instance will be type checked correspondingly. .. code-block:: python - class Box(Generic[T]): + class Box[T]: def __init__(self, content: T) -> None: self.content = content @@ -70,17 +83,14 @@ Defining subclasses of generic classes ************************************** User-defined generic classes and generic classes defined in :py:mod:`typing` -can be used as a base class for another class (generic or non-generic). For example: +can be used as base classes for other classes (generic or non-generic). For example: .. code-block:: python - from typing import Generic, TypeVar, Mapping, Iterator - - KT = TypeVar('KT') - VT = TypeVar('VT') + from typing import Mapping, Iterator # This is a generic subclass of Mapping - class MyMap(Mapping[KT, VT]): + class MyMap[KT, VT](Mapping[KT, VT]): def __getitem__(self, k: KT) -> VT: ... def __iter__(self) -> Iterator[KT]: ... def __len__(self) -> int: ... @@ -96,12 +106,12 @@ can be used as a base class for another class (generic or non-generic). For exam data: StrDict[int, int] # error: "StrDict" expects no type arguments, but 2 given data2: StrDict # OK - # This is a user-defined generic class - class Receiver(Generic[T]): - def accept(self, value: T) -> None: ... + # This is a user-defined generic class + class Receiver[T]: + def accept(self, value: T) -> None: ... - # This is a generic subclass of Receiver - class AdvancedReceiver(Receiver[T]): ... + # This is a generic subclass of Receiver + class AdvancedReceiver(Receiver[T]): ... .. note:: @@ -111,33 +121,16 @@ can be used as a base class for another class (generic or non-generic). For exam protocols like :py:class:`~typing.Iterable`, which use :ref:`structural subtyping `. -:py:class:`Generic ` can be omitted from bases if there are -other base classes that include type variables, such as ``Mapping[KT, VT]`` -in the above example. If you include ``Generic[...]`` in bases, then -it should list all type variables present in other bases (or more, -if needed). The order of type variables is defined by the following -rules: - -* If ``Generic[...]`` is present, then the order of variables is - always determined by their order in ``Generic[...]``. -* If there are no ``Generic[...]`` in bases, then all type variables - are collected in the lexicographic order (i.e. by first appearance). - For example: .. code-block:: python - from typing import Generic, TypeVar, Any + from typing import Any + class One[T]: ... + class Another[T]: ... - T = TypeVar('T') - S = TypeVar('S') - U = TypeVar('U') - - class One(Generic[T]): ... - class Another(Generic[T]): ... - - class First(One[T], Another[S]): ... - class Second(One[T], Another[S], Generic[S, U, T]): ... + class First[T, S](One[T], Another[S]): ... + class Second[S, U, T](One[T], Another[S]): ... x: First[int, str] # Here T is bound to int, S is bound to str y: Second[int, str, Any] # Here T is Any, S is int, and U is str @@ -205,8 +198,12 @@ the class definition. .. code-block:: python - # T is the type variable bound by this class - class PairedBox(Generic[T]): + from typing import TypeVar + + S = TypeVar('S') + + # T is the type parameter bound by this class + class PairedBox[T]: def __init__(self, content: T) -> None: self.content = content