Subclasses of this type describe complex numbers and include the operations
that work on the built-in complex type. These are: conversions to
complex and bool, real, imag, +,
-, *, /, abs(), conjugate(), ==, and !=. All
except - and != are abstract.

Implementors should be careful to make equal numbers equal and hash
them to the same values. This may be subtle if there are two different
extensions of the real numbers. For example, fractions.Fraction
implements hash() as follows:

We want to implement the arithmetic operations so that mixed-mode
operations either call an implementation whose author knew about the
types of both arguments, or convert both to the nearest built in type
and do the operation there. For subtypes of Integral, this
means that __add__() and __radd__() should be defined as:

There are 5 different cases for a mixed-type operation on subclasses
of Complex. I’ll refer to all of the above code that doesn’t
refer to MyIntegral and OtherTypeIKnowAbout as
“boilerplate”. a will be an instance of A, which is a subtype
of Complex (a:A<:Complex), and b:B<:Complex. I’ll consider a+b:

If A falls back to the boilerplate code, and it were to
return a value from __add__(), we’d miss the possibility
that B defines a more intelligent __radd__(), so the
boilerplate should return NotImplemented from
__add__(). (Or A may not implement __add__() at
all.)

If it falls back to the boilerplate, there are no more possible
methods to try, so this is where the default implementation
should live.

If B<:A, Python tries B.__radd__ before
A.__add__. This is ok, because it was implemented with
knowledge of A, so it can handle those instances before
delegating to Complex.

If A<:Complex and B<:Real without sharing any other knowledge,
then the appropriate shared operation is the one involving the built
in complex, and both __radd__() s land there, so a+b==b+a.

Because most of the operations on any given type will be very similar,
it can be useful to define a helper function which generates the
forward and reverse instances of any given operator. For example,
fractions.Fraction uses: