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:
When
NotImplemented
is 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 returnNotImplemented
, 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 __add__
and __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.
In use:
>>> 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