-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
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
[PEP 695] Document Python 3.12 type parameter syntax #17816
Conversation
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.
Thank you!
docs/source/generics.rst
Outdated
|
||
There are currently no plans to deprecate the legacy syntax. | ||
You can freely mix code using the new and old syntax variants, | ||
even within a single file. |
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.
PEP 695 does say you can't mix them within the same class (https://peps.python.org/pep-0695/#compatibility-with-traditional-typevars). The error cases are quite obscure though, so I'd be OK with not mentioning that.
.. code-block:: python | ||
class Shape: | ||
def set_scale[T: Shape](self: T, scale: float) -> T: |
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 is the first example using TypeVar bounds, should we introduce the syntax more explicitly?
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.
Yeah, a good idea. I'll do this in a separate PR, since it might involve moving the upper bound section, which will generate a pretty big diff.
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.
Here's the PR that changes the order of sections: #17827
Importantly, this is different from a union type, since combinations | ||
of ``str`` and ``bytes`` are not accepted: | ||
No matter which syntax you use, such a type variable is called a type variable | ||
with a value restriction. Importantly, this is different from a union type, |
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.
At runtime we call this a TypeVar with "constraints"; maybe we should also switch to this terminology in mypy?
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.
A good idea. I'll create a follow-up PR (or a documentation issue).
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.
Created an issue: #17828
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.
Nice!
docs/source/generics.rst
Outdated
There are two syntax variants for defining generic classes in Python. | ||
Python 3.12 introduced a new dedicated syntax for defining generic |
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.
It'd be nice to link to the docs — maybe this one https://docs.python.org/3/whatsnew/3.12.html#pep-695-type-parameter-syntax
class Shape: | ||
def set_scale[T: Shape](self: T, scale: float) -> T: | ||
self.scale = scale |
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.
class Shape: | |
def set_scale[T: Shape](self: T, scale: float) -> T: | |
self.scale = scale | |
from typing import Self | |
class Shape: | |
def set_scale(self, scale: float) -> Self: | |
self.scale = scale |
Since Self
is more explicit and concise, I think it's better to reference that here. We can even get rid of the legacy T = TypeVar("T", bound="Shape")
which was necessary before Self
(added in 3.11).
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.
We discuss Self
in the next section, so I'm leaving this as is. The idea is that this also explain how the Self
type works behind the scenes. It would be reasonable to introduce Self
first, but this can proposed in a separate PR, as it's not directly related to PEP 695 support.
other: "Friend | None" = None | ||
@classmethod | ||
def make_pair[T: Friend](cls: type[T]) -> tuple[T, T]: |
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.
similarly here, we can make it more concise with
def make_pair[T: Friend](cls: type[T]) -> tuple[T, T]: | |
def make_pair(cls) -> tuple[Self, Self]: |
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.
See my comment above.
docs/source/generics.rst
Outdated
@@ -400,7 +565,7 @@ Let us illustrate this by few simple examples: | |||
triangle. If we give it a callable that can calculate the area of an | |||
arbitrary shape (not just triangles), everything still works. | |||
|
|||
* :py:class:`~typing.List` is an invariant generic type. Naively, one would think | |||
* ``list`` is an invariant generic type. Naively, one would think | |||
that it is covariant, like :py:class:`~typing.Sequence` above, but consider this code: |
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.
typing.Sequence
is deprecated since 3.9 in favor of https://docs.python.org/3/library/collections.abc.html#collections.abc.Sequence
Co-authored-by: Jelle Zijlstra <jelle.zijlstra@gmail.com> Co-authored-by: Brian Schubert <brianm.schubert@gmail.com>
Finish work started in #17816. Document `type` statement when discussing type aliases. Update some examples to have both old-style and new-style variants. In less common scenarios, examples only use a single syntax variant to reduce verbosity. Also update some examples to generally use more modern features. Closes #17810.
Provide examples using both syntax variants, and give both of the syntax variants similar prominence. It's likely that both syntax variants will continue to be widely used for a long time.
Also adjust terminology (e.g. use 'type parameter' / 'type argument' more consistently), since otherwise some descriptions would be unclear.
I didn't update examples outside the generics chapter. I'll do this in a follow-up PR.
Work on #17810.