This rule raises an issue when a special method raises a NotImplementedError instead of returning NotImplemented.
In Python, special methods corresponding to numeric operators and rich comparison operators should return NotImplemented when the
operation is not supported.
For example A + B is equivalent to calling A.__add__(B). If this binary operation is not supported by class A,
A.__add__(B) should return NotImplemented. The interpreter will then try the reverse operation, i.e.
B.__radd__(A). If these special methods were to raise NotImplementedError, the callers would not catch the exception and the
reverse operation would not be called.
Below is the list of special methods this rule applies to:
__lt__(self, other) __le__(self, other) __eq__(self, other) __ne__(self, other) __gt__(self, other) __ge__(self, other) __add__(self, other) __sub__(self, other) __mul__(self, other) __matmul__(self, other) __truediv__(self, other) __floordiv__(self, other) __mod__(self, other) __divmod__(self, other) __pow__(self, other[, modulo]) __lshift__(self, other) __rshift__(self, other) __and__(self, other) __xor__(self, other) __or__(self, other) __radd__(self, other) __rsub__(self, other) __rmul__(self, other) __rmatmul__(self, other) __rtruediv__(self, other) __rfloordiv__(self, other) __rmod__(self, other) __rdivmod__(self, other) __rpow__(self, other[, modulo]) __rlshift__(self, other) __rrshift__(self, other) __rand__(self, other) __rxor__(self, other) __ror__(self, other) __iadd__(self, other) __isub__(self, other) __imul__(self, other) __imatmul__(self, other) __itruediv__(self, other) __ifloordiv__(self, other) __imod__(self, other) __ipow__(self, other[, modulo]) __ilshift__(self, other) __irshift__(self, other) __iand__(self, other) __ixor__(self, other) __ior__(self, other) __length_hint__(self) Make sure special methods return NotImplemented instead of raising a NotImplementedError.
class MyClass:
def __add__(self, other):
raise NotImplementedError() # Noncompliant: the exception will be propagated
def __radd__(self, other):
raise NotImplementedError() # Noncompliant: the exception will be propagated
class MyOtherClass:
def __add__(self, other):
return 42
def __radd__(self, other):
return 42
MyClass() + MyOtherClass() # This will raise NotImplementedError
class MyClass:
def __add__(self, other):
return NotImplemented
def __radd__(self, other):
return NotImplemented
class MyOtherClass:
def __add__(self, other):
return 42
def __radd__(self, other):
return 42
MyClass() + MyOtherClass() # This returns 42
The __length_hint__ special method also requires to return a NotImplemented. Its behavior differs from the other methods,
because when it returns NotImplemented, a default value will be returned instead. See PEP
424 for more information.
__length_hint__