From ea0bbf8c6637ae454ab4408bd6251b670f1fffac Mon Sep 17 00:00:00 2001 From: Wim Glenn Date: Tue, 15 Sep 2020 10:59:49 -0500 Subject: [PATCH 1/5] 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. --- Doc/reference/datamodel.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst index a817408c3b1ef5..0f28831f439c5f 100644 --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -2376,7 +2376,7 @@ left undefined. .. note:: - If the right operand's type is a subclass of the left operand's type and that + If the right operand's type is a strict subclass of the left operand's type and that subclass provides the reflected method for the operation, this method will be called before the left operand's non-reflected method. This behavior allows subclasses to override their ancestors' operations. From b1b6390369767a1e6fa21bd3ce19a9bba5814ef0 Mon Sep 17 00:00:00 2001 From: Wim Glenn Date: Tue, 15 Sep 2020 16:58:22 -0500 Subject: [PATCH 2/5] add missing word in footnote --- Doc/reference/datamodel.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst index 0f28831f439c5f..f45a4ca25fa2ac 100644 --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -2772,5 +2772,5 @@ An example of an asynchronous context manager class:: *blocking* such fallback. .. [#] For operands of the same type, it is assumed that if the non-reflected method - (such as :meth:`__add__`) fails the operation is not supported, which is why the + (such as :meth:`__add__`) fails then the operation is not supported, which is why the reflected method is not called. From bd9177f7b408c17e644dbc3fe30ef6627b436575 Mon Sep 17 00:00:00 2001 From: Wim Glenn Date: Thu, 17 Sep 2020 12:43:25 -0500 Subject: [PATCH 3/5] simplify the rationale in the 'note' and specify the behaviour fully in the main text --- Doc/reference/datamodel.rst | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst index f45a4ca25fa2ac..e954571056fff1 100644 --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -2363,11 +2363,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 + (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, ``y.__rsub__(x)`` - is called if ``x.__sub__(y)`` returns *NotImplemented*. + is called if ``x.__sub__(y)`` returns *NotImplemented* or ``type(y)`` is a + subclass of ``type(x)``. .. index:: builtin: pow @@ -2376,10 +2378,9 @@ left undefined. .. note:: - If the right operand's type is a strict subclass of the left operand's type and that - subclass provides the reflected method for the operation, this method will be - called before the left operand's non-reflected method. This behavior allows - subclasses to override their ancestors' operations. + 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. .. method:: object.__iadd__(self, other) From 41c82db305456a151d77c825b10fb2f3b8be37b7 Mon Sep 17 00:00:00 2001 From: Wim Glenn Date: Thu, 17 Sep 2020 19:55:23 -0500 Subject: [PATCH 4/5] convert inline note to footnote --- Doc/reference/datamodel.rst | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst index e954571056fff1..ad5e753c432913 100644 --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -2369,19 +2369,13 @@ left undefined. class. [#]_ For instance, to evaluate the expression ``x - y``, where *y* is an instance of a class that has an :meth:`__rsub__` method, ``y.__rsub__(x)`` is called if ``x.__sub__(y)`` returns *NotImplemented* or ``type(y)`` is a - subclass of ``type(x)``. + subclass of ``type(x)``. [#]_ .. index:: builtin: pow Note that ternary :func:`pow` will not try calling :meth:`__rpow__` (the coercion rules would become too complicated). - .. note:: - - 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. - .. method:: object.__iadd__(self, other) object.__isub__(self, other) @@ -2775,3 +2769,7 @@ An example of an asynchronous context manager class:: .. [#] For operands of the same type, it is assumed that if the non-reflected method (such as :meth:`__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. From 6e91910bbb0debe1a02432e03b282c2bbc501cfe Mon Sep 17 00:00:00 2001 From: Ethan Furman Date: Thu, 24 Oct 2024 20:12:53 -0700 Subject: [PATCH 5/5] Update Doc/reference/datamodel.rst --- Doc/reference/datamodel.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst index f744a72372d22d..e5f2dcd5bc9523 100644 --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -3336,7 +3336,7 @@ left undefined. :func:`pow`, ``**``, ``<<``, ``>>``, ``&``, ``^``, ``|``) with reflected (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 + 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)``