Here is a small repro - class A and B are exactly the same, with the dunder method implemented for the reflected right shift operator. So, x >> y
is expected to resolve to y.__rrshift__(x)
.
class A:
def __init__(self, x):
self.x = x
def __rrshift__(self, other):
return self.__class__(self.x other.x)
class B:
def __init__(self, x):
self.x = x
def __rrshift__(self, other):
return self.__class__(self.x other.x)
However, the dunder method doesn't work on instances of the same class.
A(1) >> A(2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for >>: 'A' and 'A'
While it works for instances from different classes.
A(1) >> B(2)
<__main__.B object at 0x7f6ca8294f40>
This was pretty surprising. And seems to be common behavior across other reflected operators too (like, radd
). Is there a reason this doesn't work?
CodePudding user response:
As the doc states, it works when operands are of different type
These functions are only called if the left operand does not support the corresponding operation and the operands are of different types
It seems you only need __rshift__
in both classes (only in A is valid for your examples)
def __rshift__(self, other):
return self.__class__(self.x other.x)
CodePudding user response:
From the docs (section 3.3.8. Emulating numeric types in the Python Language Reference Manual):
These functions are only called if the left operand does not support the corresponding operation [3] and the operands are of different types. [4]
where footnote 4 reads:
[4] For operands of the same type, it is assumed that if the non-reflected method – such as
__add__()
– fails then the overall operation is not supported, which is why the reflected method is not called.
So, like it or not, the behavior is intended and documented.