]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.11] Clarify `Self` interaction with subclasses (GH-107511) (#107549)
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Tue, 1 Aug 2023 20:31:22 +0000 (13:31 -0700)
committerGitHub <noreply@github.com>
Tue, 1 Aug 2023 20:31:22 +0000 (20:31 +0000)
Co-authored-by: Alexandru Mărășteanu <alexei@users.noreply.github.com>
Doc/library/typing.rst

index b6bb50b65db6207c32ab2acf2d3cec79d5b192a0..0419f6799c6646b6d89b7463c6f0aacf0a0fb1fa 100644 (file)
@@ -905,13 +905,17 @@ using ``[]``.
 
    For example::
 
-      from typing import Self
+      from typing import Self, reveal_type
 
       class Foo:
           def return_self(self) -> Self:
               ...
               return self
 
+      class SubclassOfFoo(Foo): pass
+
+      reveal_type(Foo().return_self())  # Revealed type is "Foo"
+      reveal_type(SubclassOfFoo().return_self())  # Revealed type is "SubclassOfFoo"
 
    This annotation is semantically equivalent to the following,
    albeit in a more succinct fashion::
@@ -925,15 +929,11 @@ using ``[]``.
               ...
               return self
 
-   In general if something currently follows the pattern of::
-
-      class Foo:
-          def return_self(self) -> "Foo":
-              ...
-              return self
-
-   You should use :data:`Self` as calls to ``SubclassOfFoo.return_self`` would have
-   ``Foo`` as the return type and not ``SubclassOfFoo``.
+   In general, if something returns ``self``, as in the above examples, you
+   should use ``Self`` as the return annotation. If ``Foo.return_self`` was
+   annotated as returning ``"Foo"``, then the type checker would infer the
+   object returned from ``SubclassOfFoo.return_self`` as being of type ``Foo``
+   rather than ``SubclassOfFoo``.
 
    Other common use cases include:
 
@@ -941,6 +941,17 @@ using ``[]``.
      of the ``cls`` parameter.
    - Annotating an :meth:`~object.__enter__` method which returns self.
 
+   You should not use ``Self`` as the return annotation if the method is not
+   guaranteed to return an instance of a subclass when the class is
+   subclassed::
+
+      class Eggs:
+          # Self would be an incorrect return annotation here,
+          # as the object returned is always an instance of Eggs,
+          # even in subclasses
+          def returns_eggs(self) -> "Eggs":
+              return Eggs()
+
    See :pep:`673` for more details.
 
    .. versionadded:: 3.11