-
Notifications
You must be signed in to change notification settings - Fork 293
Update generics reference to use PEP 695 type parameter syntax #2242
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 8 commits
2d41749
0225ec1
3bf5bbd
de35f89
c624188
1d49b93
ba00969
153ab60
f8d68e2
250f302
9f76605
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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]): ... | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This one should also have
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. hi @JelleZijlstra, Thanks for the feedback! I’ve updated |
||
|
|
||
| .. 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 <protocol-types>`. | ||
|
|
||
| :py:class:`Generic <typing.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 | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This still uses the old syntax. Please make sure all examples (other than the one mentioning the old syntax explicitly) use the new syntax.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the review @JelleZijlstra, I’ve updated the remaining example to use PEP 695 syntax so that all examples are now consistent, with the old syntax kept only in the explicitly marked compatibility section.