Issue 1002453: Wrong documentation of radd etc. (original) (raw)
Info node 'Emulating numeric types' says:
radd(self, other) rsub(self, other) ... These functions are only called if the left operand does not support the corresponding operation.
Not so. Info node 'Coercion rules' lists one exception:
if the left operand is an instance of a built-in
type or a new-style class, and the right operand is
an instance of a proper subclass of that type or
class, the right operand's __rop__()' method is tried _before_ the left operand's
op()' method.
...and one time where above the text is misleading:
When either operand type defines a coercion, this
coercion is called before that type's __op__()' or
rop()' method is called, but no sooner. If the
coercion returns an object of a different type for
the operand whose coercion is invoked, part of the
process is redone using the new object.
Thus, Python can call rop(self, other) even if self.op exists: If one does `x - y' where y.coerce(x) coerces x to y's class, y.rsub(x) is called instead of (coerced x).sub(y). I think this should be documented in the 'Emulating numeric types' node. Unless Python is changed to redo the choice between op, rop and iop after coercion.
I think it would also be good to explain in that Info node what op and rop can do if they do not support the operation with the supplied arguments, but the other argument might support it. It seems obvious that self.op(other) can simply attempt to call other.rop(self) and let that fail if it is not supported. However, the above rules seem to mean that self.rop(other) might want to call other.op(self) too, which could lead to infinite recursion. Are there some special times where it can do that, and other times where it should not?