From 298e04163188639fa28dd86cc9d1b8096199f6fb Mon Sep 17 00:00:00 2001 From: Wim Jeantine-Glenn Date: Tue, 29 Oct 2024 18:02:27 -0500 Subject: bpo-41793: Fix an inaccuracy about reflected methods in datamodel docs (GH-22257) * Qualifying that the right operand's type must be a *strict* subclass for the reflected method to take precedence avoids an edge case / counter-example when the types are actually equal. Co-authored-by: Ethan Furman --- Doc/reference/datamodel.rst | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst index f56bd5e..e5f2dcd 100644 --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -3334,12 +3334,13 @@ left undefined. These methods are called to implement the binary arithmetic operations (``+``, ``-``, ``*``, ``@``, ``/``, ``//``, ``%``, :func:`divmod`, :func:`pow`, ``**``, ``<<``, ``>>``, ``&``, ``^``, ``|``) with reflected - (swapped) operands. These functions are only called if the left operand does - not support the corresponding operation [#]_ and the operands are of different - types. [#]_ For instance, to evaluate the expression ``x - y``, where *y* is - an instance of a class that has an :meth:`__rsub__` method, - ``type(y).__rsub__(y, x)`` is called if ``type(x).__sub__(x, y)`` returns - :data:`NotImplemented`. + (swapped) operands. These functions are only called if the operands + are of different types, when the left operand does not support the corresponding + operation [#]_, or the right operand's class is derived from the left operand's + class. [#]_ For instance, to evaluate the expression ``x - y``, where *y* is + an instance of a class that has an :meth:`__rsub__` method, ``type(y).__rsub__(y, x)`` + is called if ``type(x).__sub__(x, y)`` returns :data:`NotImplemented` or ``type(y)`` + is a subclass of ``type(x)``. [#]_ .. index:: pair: built-in function; pow @@ -3354,7 +3355,6 @@ left undefined. non-reflected method. This behavior allows subclasses to override their ancestors' operations. - .. method:: object.__iadd__(self, other) object.__isub__(self, other) object.__imul__(self, other) @@ -3881,7 +3881,10 @@ An example of an asynchronous context manager class:: method—that will instead have the opposite effect of explicitly *blocking* such fallback. -.. [#] For operands of the same type, it is assumed that if the non-reflected - method -- such as :meth:`~object.__add__` -- fails then the overall - operation is not - supported, which is why the reflected method is not called. +.. [#] For operands of the same type, it is assumed that if the non-reflected method + (such as :meth:`~object.__add__`) fails then the operation is not supported, which is why the + reflected method is not called. + +.. [#] If the right operand's type is a subclass of the left operand's type, the + reflected method having precedence allows subclasses to override their ancestors' + operations. -- cgit v0.12