Skip to content
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

Merged
merged 13 commits into from
Sep 25, 2024
Merged

Conversation

JukkaL
Copy link
Collaborator

@JukkaL JukkaL commented Sep 24, 2024

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.

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
Copy link
Member

@JelleZijlstra JelleZijlstra left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you!


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.
Copy link
Member

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:
Copy link
Member

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?

Copy link
Collaborator Author

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.

Copy link
Collaborator Author

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,
Copy link
Member

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?

Copy link
Collaborator Author

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).

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Created an issue: #17828

Copy link
Contributor

@Hnasar Hnasar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!

Comment on lines 40 to 41
There are two syntax variants for defining generic classes in Python.
Python 3.12 introduced a new dedicated syntax for defining generic
Copy link
Contributor

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

Comment on lines +325 to +328
class Shape:
def set_scale[T: Shape](self: T, scale: float) -> T:
self.scale = scale
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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).

Copy link
Collaborator Author

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]:
Copy link
Contributor

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

Suggested change
def make_pair[T: Friend](cls: type[T]) -> tuple[T, T]:
def make_pair(cls) -> tuple[Self, Self]:

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See my comment above.

@@ -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:
Copy link
Contributor

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

JukkaL and others added 3 commits September 25, 2024 11:19

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
Co-authored-by: Jelle Zijlstra <jelle.zijlstra@gmail.com>
Co-authored-by: Brian Schubert <brianm.schubert@gmail.com>

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
@JukkaL JukkaL merged commit 58825f7 into master Sep 25, 2024
2 checks passed
@JukkaL JukkaL deleted the generics-docs branch September 25, 2024 11:45
JukkaL added a commit that referenced this pull request Sep 25, 2024
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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants