Lesson 12 - Magic Methods in Python - Math methods
In the previous lesson, Magic Methods in Python, we introduced magic methods. In today's
Python tutorial, we're going to continue with them. This time, we're going to
show special methods for mathematical operators. We'll also show their use on
the Vector
class.
Standard operators
These operators are called automatically on an object a
when
used like this:
c = a + b
The object a
is passed through the self
parameter
and the object b
is the other
parameter.
__add__(self, other)
The method is called on the first object when the +
operator is
used:
c = a + b
__sub__(self, other)
The method is called when subtracting by the -
operator:
c = a - b
__mul__(self, other)
The method is called when multiplying by the *
operator:
c = a * b
__truediv__(self, other)
The method is called when dividing by the /
operator:
c = a / b
__floordiv__(self, other)
The method is called when dividing by the //
operator
(whole-number division):
c = a // b
__mod__(self, other)
The method is called when getting the remainder after the whole-number
division by using the modulo operator %
:
c = a % b
__divmod__(self, other)
Returns a pair (a // b, a % b)
for integers:
c = divmod(a, b)
__pow__(self, other, modulo)
The method is executed when we use the power **
operator. The
method should be able to take a third, optional (modulo) argument (https://docs.python.org/…nctions.html#pow):
c = a ** b
__lshift__(self, other)
Executed when using the left bit-shift operator <<
:
c = a << b
__rshift__(self, other)
Executed when using the right bit-shift operator >>
:
c = a >> b
__and__(self, other)
Executed when using the bitwise AND operator &
:
c = a & b
__xor__(self, other)
Executed when using the bitwise XOR operator ^
(Non-Equivalence):
c = a ^ b
__or__(self, other)
Executed when using the bitwise OR operator |
:
c = a | b
Reversed operators
Reversed operators are called on the second object when the first object doesn't implement the operator.
For example:
sth = 1 + my_object
If the __add__()
magic method isn't supported by
int
, which is probably not, the __radd__()
method is
called on my_object
.
These operators are called automatically on the object b
, with
object b
being the self
parameter and object
a
being the other parameter.
__radd__(self, other)
- Adding__rsub__(self, other)
- Subtracting__rmul__(self, other)
- Multiplying__rtruediv__(self, other)
- True division__rfloordiv__(self, other)
- Whole-number division__rmod__(self, other)
- The remainder after whole-number division - modulo__rdivmod__(self, other)
- Returns a pair(a // b, a % b)
for integers__rpow__(self, other, modulo)
- Power__rlshift__(self, other)
- Left bit-shift__rrshift__(self, other)
- Right bit-shift__rand__(self, other)
- Bitwise AND__rxor__(self, other)
- Bitwise XOR (Non-Equivalence)__ror__(self, other)
- Bitwise OR
In place operators
These operators allow us to use a shortened notation (in place). The
parameters of the methods are self
and other
, but
return a modified self
. If there's no method, Python will try to
emulate it using defined methods.
An example:
my_object += 1
Python calls the __iadd__()
method. If it fails, it calls
__add__()
as follows:
temp = my_object + 1 # calls __add__() my_object = temp
__iadd__(self, other)
- Adding__isub__(self, other)
- Subtracting__imul__(self, other)
- Multiplication__itruediv__(self, other)
- True division__ifloordiv__(self, other)
- Whole-number division__imod__(self, other)
The remainder of whole-number division - modulo__ipow__(self, other, modulo)
- Power__ilshift__(self, other)
- Left bit-shift__irshift__(self, other)
Right bit-shift__iand__(self, other)
- Bitwise AND__ixor__(self, other)
- Bitwise XOR (Non-Equivalence)__ior__(self, other)
- Bitwise OR
Other magic methods
__neg__(self)
Unary minus:
-a
__pos__(self)
Unary plus:
+a
__abs__(self)
Absolute value implementing behavior for abs()
:
abs(a)
__invert__(self)
Unary inversion:
~a
__complex__(self)
Implements behavior for the complex()
function:
complex(a)
__int__(self)
Implements behavior for int()
:
int(a)
__float__(self)
Implements behavior for float()
:
float(a)
__round__(self, n)
Implements behavior for round()
:
round(a)
__index__(self)
Python uses this method to convert numeric types to int
, for
example, when truncating or using the built-in bin()
,
hex()
, and oct()
functions. This method should return
the same result as the __int__()
magic method. It should also
return an integer (int
).
Method examples
Let's create a simple Vector
class, holding its 2 x
and y
components. We'll implement some of the magic methods on
it.
class Vector: def __init__(self, x, y): self.x = float(x) self.y = float(y) def __str__(self): return "({0.x}, {0.y})".format(self) ...
The beginning is probably clear. In the __str__()
method, we get
the x
and y
attributes from self
.
def __add__(self, other): if isinstance(other, Vector): return Vector(self.x+other.x, self.y+other.y) elif issubclass(type(other), Sequence): if len(other) == 2: return Vector(self.x+other[0], self.y+other[1]) raise NotImplemented
First we compare whether the second object is also a Vector
. If
so, we return the sum of the x
and y
components as a
new Vector
.
Further branching is more complex. Using the built-in
issubclass()
function, we check if the second object class is a
subclass of Sequence
of the collections.abc
module.
This allows us to use the len()
function on the object to get the
first and second elements from the object. Without worrying that the object
wouldn't support it. If both branches fail and don't return anything, the
NotImplemented
exception is thrown.
def __mul__(self, other): if issubclass(type(other), Real): return Vector(self.x * other, self.y * other) raise NotImplemented
Here we check if other
is a subclass of Real
(real
number) from the numbers
module. Therefore, we can multiply the
Vector
by int
or float
and avoid
unnecessary branching and checking of object types.
The classes in the numbers
and collections.abc
modules are actually abstract base classes. These are classes where we have to
implement a certain object interface if we inherit them. But let's wait with
this for the next lesson, Magic Methods in Python - Collections and Descriptors.
Did you have a problem with anything? Download the sample application below and compare it with your project, you will find the error easily.
Download
By downloading the following file, you agree to the license terms
Downloaded 2x (2.69 kB)
Application includes source codes in language Python