PEP 696: some suggestions to make the text clearer (#3641)
* Moves TypeVarTuple discussion so the text flows better. Otherwise, it feels to me like an awkward interlude between the paragraph introducing rules and the actual rules. * In sections where the text uses `T1` and `T2` as TypeVar names, changes the examples to use the same names. * Fix subtyping relationship in "Bound Rules." * Spell out subclassing rules in the text, rather than leaning so much on the example. Co-authored-by: Jelle Zijlstra <jelle.zijlstra@gmail.com> Co-authored-by: James Hilton-Balfe <gobot1234yt@gmail.com>
This commit is contained in:
parent
67c0d14227
commit
2b913684ca
|
@ -216,19 +216,8 @@ default to the type of ``start`` and step default to ``int | None``.
|
||||||
Foo[int](1, "") # Invalid: Foo[int, str] cannot be assigned to self: Foo[int, int] in Foo.__init__
|
Foo[int](1, "") # Invalid: Foo[int, str] cannot be assigned to self: Foo[int, int] in Foo.__init__
|
||||||
Foo[int]("", 1) # Invalid: Foo[str, int] cannot be assigned to self: Foo[int, int] in Foo.__init__
|
Foo[int]("", 1) # Invalid: Foo[str, int] cannot be assigned to self: Foo[int, int] in Foo.__init__
|
||||||
|
|
||||||
When using a type parameter as the default to another type parameter.
|
When using a type parameter as the default to another type parameter, the
|
||||||
Where ``T1`` is the default for ``T2`` the following rules apply.
|
following rules apply, where ``T1`` is the default for ``T2``.
|
||||||
|
|
||||||
``TypeVarTuple``\s are not supported because:
|
|
||||||
|
|
||||||
- `Scoping Rules`_ does not allow usage of type parameters
|
|
||||||
from outer scopes.
|
|
||||||
- Multiple ``TypeVarTuple``\s cannot appear in the type
|
|
||||||
parameter list for a single object, as specified in
|
|
||||||
:pep:`646#multiple-type-variable-tuples-not-allowed`.
|
|
||||||
|
|
||||||
These reasons leave no current valid location where a
|
|
||||||
``TypeVarTuple`` could be used as the default of another ``TypeVarTuple``.
|
|
||||||
|
|
||||||
Scoping Rules
|
Scoping Rules
|
||||||
~~~~~~~~~~~~~
|
~~~~~~~~~~~~~
|
||||||
|
@ -237,11 +226,11 @@ Scoping Rules
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
DefaultT = TypeVar("DefaultT", default=T)
|
T2 = TypeVar("T2", default=T1)
|
||||||
|
|
||||||
class Foo(Generic[T, DefaultT]): ... # Valid
|
class Foo(Generic[T1, T2]): ... # Valid
|
||||||
class Foo(Generic[T]):
|
class Foo(Generic[T1]):
|
||||||
class Bar(Generic[DefaultT]): ... # Valid
|
class Bar(Generic[T2]): ... # Valid
|
||||||
|
|
||||||
StartT = TypeVar("StartT", default="StopT") # Swapped defaults around from previous example
|
StartT = TypeVar("StartT", default="StopT") # Swapped defaults around from previous example
|
||||||
StopT = TypeVar("StopT", default=int)
|
StopT = TypeVar("StopT", default=int)
|
||||||
|
@ -253,14 +242,14 @@ Using a type parameter from an outer scope as a default is not supported.
|
||||||
Bound Rules
|
Bound Rules
|
||||||
~~~~~~~~~~~
|
~~~~~~~~~~~
|
||||||
|
|
||||||
``T2``'s bound must be a subtype of ``T1``'s bound.
|
``T1``'s bound must be a subtype of ``T2``'s bound.
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
T = TypeVar("T", bound=float)
|
T1 = TypeVar("T1", bound=int)
|
||||||
TypeVar("Ok", default=T, bound=int) # Valid
|
TypeVar("Ok", default=T1, bound=float) # Valid
|
||||||
TypeVar("AlsoOk", default=T, bound=float) # Valid
|
TypeVar("AlsoOk", default=T1, bound=int) # Valid
|
||||||
TypeVar("Invalid", default=T, bound=str) # Invalid: str is not a subtype of float
|
TypeVar("Invalid", default=T1, bound=str) # Invalid: int is not a subtype of str
|
||||||
|
|
||||||
Constraint Rules
|
Constraint Rules
|
||||||
~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~
|
||||||
|
@ -329,7 +318,10 @@ Subclassing
|
||||||
'''''''''''
|
'''''''''''
|
||||||
|
|
||||||
Subclasses of ``Generic``\ s with type parameters that have defaults
|
Subclasses of ``Generic``\ s with type parameters that have defaults
|
||||||
behave similarly to ``Generic`` ``TypeAlias``\ es.
|
behave similarly to ``Generic`` ``TypeAlias``\ es. That is, subclasses can be
|
||||||
|
further subscripted following normal subscription rules, non-overridden
|
||||||
|
defaults should be substituted in, and type parameters with such defaults can be
|
||||||
|
further specialised down the line.
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
|
@ -421,6 +413,20 @@ for the ``ParamSpec`` and one for the ``TypeVarTuple``.
|
||||||
Foo[int, str] # Ts = (int, str), P = [float, bool]
|
Foo[int, str] # Ts = (int, str), P = [float, bool]
|
||||||
Foo[int, str, [bytes]] # Ts = (int, str), P = [bytes]
|
Foo[int, str, [bytes]] # Ts = (int, str), P = [bytes]
|
||||||
|
|
||||||
|
``TypeVarTuple``\ s as Defaults
|
||||||
|
'''''''''''''''''''''''''''''''
|
||||||
|
|
||||||
|
Using a ``TypeVarTuple`` as a default is not supported because:
|
||||||
|
|
||||||
|
- `Scoping Rules`_ does not allow usage of type parameters
|
||||||
|
from outer scopes.
|
||||||
|
- Multiple ``TypeVarTuple``\ s cannot appear in the type
|
||||||
|
parameter list for a single object, as specified in
|
||||||
|
:pep:`646#multiple-type-variable-tuples-not-allowed`.
|
||||||
|
|
||||||
|
These reasons leave no current valid location where a
|
||||||
|
``TypeVarTuple`` could be used as the default of another ``TypeVarTuple``.
|
||||||
|
|
||||||
Binding rules
|
Binding rules
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue