I was looking at the implementation of Complex
in the numbers
module and noticed __sub__
and __rsub__
s implementation that looked like this:
def __sub__(self, other):
""" self - other """
return self + -other
def __rsub__(self, other):
""" other - self """
return -self + other
This confused me.
Firstly, I'm not really sure why these were implemented (guessing all subclasses of Complex
can fall-back to it?) and, secondly, I can't understand why they chose to use the unary -
like this for its implementation.
Any ideas?
This is a generic implementation that subclasses can use, yes, if they so desire. This is an additional goal; the primary goal of these ABC types is to be able to duck-type numeric types (see PEP 3141 – A Type Hierarchy for Numbers.
The implementation uses unary minus to avoid recursion; if you used self - other
then Python uses self.__sub__(other)
or self.__rsub__(other)
again.
Because subtraction can be cast as addition with a unary minus operation, the authors of the ABC were able to provide you these methods as a bonus; the alternative would be to provide @abstracmethod
methods instead, forcing subclasses to provide a concrete implementation. Your subclass can now, optionally, implement those methods in a different way if that is more efficient, but they don't have to.
This is a pattern used in all ABCs the standard library provides. If you take a look at the documentation for the collections.abc
module you'll notice a Mixin Methods column; these are all methods the respective ABC has provided as concrete implementations that may or may not rely on the abstract methods defined by that ABC or its base classes.
Also see the general PEP 3119 – Introducing Abstract Base Classes upon which PEP 3141 is built:
Some ABCs also provide concrete (i.e. non-abstract) methods; for example, the
Iterator
class has an__iter__
method returning itself, fulfilling an important invariant of iterators (which in Python 2 has to be implemented anew by each iterator class). These ABCs can be considered "mix-in" classes.