From: Alexandru Mărășteanu Date: Tue, 1 Aug 2023 20:20:25 +0000 (+0100) Subject: Clarify `Self` interaction with subclasses (#107511) X-Git-Tag: v3.13.0a1~1108 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=c8872f4285d3b61c252e3384bec6d30618b7d698;p=thirdparty%2FPython%2Fcpython.git Clarify `Self` interaction with subclasses (#107511) --- diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst index f96a805cef7b..fad945ffc821 100644 --- a/Doc/library/typing.rst +++ b/Doc/library/typing.rst @@ -963,13 +963,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:: @@ -983,15 +987,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: @@ -999,6 +999,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