Skip to content

Commit 5d3c1f8

Browse files
authored
Update generics.rst
1 parent a1d4d07 commit 5d3c1f8

File tree

1 file changed

+44
-21
lines changed

1 file changed

+44
-21
lines changed

docs/spec/generics.rst

Lines changed: 44 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -93,8 +93,9 @@ This is equivalent to omitting the generic notation and just saying
9393
User-defined generic types
9494
--------------------------
9595

96-
You can include a ``Generic`` base class to define a user-defined class
97-
as generic. Example::
96+
You can define a user-defined class as generic by including a ``Generic``
97+
base class, either explicitly or implicitly via the ``Protocol[T]``
98+
shorthand for :ref:`generic protocols<generic-protocols>`. Example::
9899

99100
from typing import TypeVar, Generic
100101
from logging import Logger
@@ -144,7 +145,6 @@ A generic type can have any number of type variables, and type variables
144145
may be constrained. This is valid::
145146

146147
from typing import TypeVar, Generic
147-
...
148148

149149
T = TypeVar('T')
150150
S = TypeVar('S')
@@ -156,29 +156,16 @@ Each type variable argument to ``Generic`` must be distinct. This is
156156
thus invalid::
157157

158158
from typing import TypeVar, Generic
159-
...
160159

161160
T = TypeVar('T')
162161

163162
class Pair(Generic[T, T]): # INVALID
164163
...
165164

166-
The ``Generic[T]`` base class is redundant in simple cases where you
167-
subclass some other generic class and specify type variables for its
168-
parameters::
169-
170-
from typing import TypeVar
171-
from collections.abc import Iterator
172-
173-
T = TypeVar('T')
174-
175-
class MyIter(Iterator[T]):
176-
...
177-
178-
That class definition is equivalent to::
179-
180-
class MyIter(Iterator[T], Generic[T]):
181-
...
165+
When no ``Generic[T]`` or ``Protocol[T]`` base class is present, a defined
166+
class is generic if you subclass one or more other generic classes and
167+
specify type variables for their parameters. See :ref:`generic-base-classes`
168+
for details.
182169

183170
You can use multiple inheritance with ``Generic``::
184171

@@ -402,6 +389,7 @@ instead is preferred. (First, creating the subscripted class,
402389
e.g. ``Node[int]``, has a runtime cost. Second, using a type alias
403390
is more readable.)
404391

392+
.. _`generic-base-classes`:
405393

406394
Arbitrary generic types as base classes
407395
---------------------------------------
@@ -458,8 +446,43 @@ Also consider the following example::
458446
class MyDict(Mapping[str, T]):
459447
...
460448

461-
In this case MyDict has a single parameter, T.
449+
In this case ``MyDict`` has a single parameter, ``T``.
450+
451+
Type variables are applied to the defined class in the order in which
452+
they first appear in any generic base classes::
462453

454+
from typing import Generic, TypeVar
455+
456+
T1 = TypeVar('T1')
457+
T2 = TypeVar('T2')
458+
T3 = TypeVar('T3')
459+
460+
class Parent1(Generic[T1, T2]):
461+
...
462+
class Parent2(Generic[T1, T2]):
463+
...
464+
class Child(Parent1[T1, T3], Parent2[T2, T3]):
465+
...
466+
467+
That ``Child`` definition is equivalent to::
468+
469+
class Child(Parent1[T1, T3], Parent2[T2, T3], Generic[T1, T3, T2]):
470+
...
471+
472+
Type checkers may warn when the type variable order is inconsistent::
473+
474+
from typing import Generic, TypeVar
475+
476+
T1 = TypeVar('T2')
477+
T2 = TypeVar('T2')
478+
T3 = TypeVar('T3')
479+
480+
class Grandparent(Generic[T1, T2]):
481+
...
482+
class Parent(Grandparent[T1, T2]):
483+
...
484+
class Child(Parent[T1, T2], Grandparent[T2, T1]): # Inconsistent order
485+
...
463486

464487
Abstract generic types
465488
----------------------

0 commit comments

Comments
 (0)