If your class doesn't implement a specific overloaded operator for the argument types provided, it should
return NotImplemented (note that this is a special constant, not the same as
NotImplementedError). This will allow Python to fall back to trying other methods to make the operation work:
NotImplementedis returned, the interpreter will then try the reflected operation on the other type, or some other fallback, depending on the operator. If all attempted operations return
NotImplemented, the interpreter will raise an appropriate exception.
For example, given
x + y, if
x.__add__(y) returns unimplemented,
y.__radd__(x) is attempted instead.
class NotAddable(object): def __init__(self, value): self.value = value def __add__(self, other): return NotImplemented class Addable(NotAddable): def __add__(self, other): return Addable(self.value + other.value) __radd__ = __add__
As this is the reflected method we have to implement
__radd__ to get the expected behaviour in all cases; fortunately, as they are both doing the same thing in this simple example, we can take a shortcut.
>>> x = NotAddable(1) >>> y = Addable(2) >>> x + x Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unsupported operand type(s) for +: 'NotAddable' and 'NotAddable' >>> y + y <so.Addable object at 0x1095974d0> >>> z = x + y >>> z <so.Addable object at 0x109597510> >>> z.value 3