10.7. OOP Operator Overload

10.7.1. Why to use operator overload?

  • Readable syntax

  • Simpler operations

class Vector:
    def __init__(self, x=0, y=0):
        self.x = x
        self.y = y

    def __str__(self):
        return f'Vector(x={self.x}, y={self.y})'

vector1 = Vector(x=1, y=2)
vector2 = Vector(x=3, y=4)
vector3 = Vector(x=5, y=6)

output = vector1 + vector2
# TypeError: unsupported operand type(s) for +: 'Vector' and 'Vector'

output = vector1 + vector2 + vector3
# TypeError: unsupported operand type(s) for +: 'Vector' and 'Vector'
class Vector:
    def __init__(self, x=0, y=0):
        self.x = x
        self.y = y

    def __str__(self):
        return f'Vector(x={self.x}, y={self.y})'

    def __add__(self, other):
        return Vector(
            self.x + other.x,
            self.y + other.y
        )

vector1 = Vector(x=1, y=2)
vector2 = Vector(x=3, y=4)
vector3 = Vector(x=5, y=6)

output = vector1 + vector2
print(output)
# Vector(x=4, y=6)

output = vector1 + vector2 + vector3
print(output)
# Vector(x=9, y=12)

10.7.2. Operator Overload

10.7.2.1. Numerical Operators

Table 20. Numerical Operator Overload

Operator

Method

a + b

a.__add__(b)

a += b

a.__iadd__(b)

a - b

a.__sub__(b)

a -= b

a.__isub__(b)

a * b

a.__mul__(b)

a *= b

a.__imul__(b)

a / b

a.__div__(b)

a /= b

a.__idiv__(b)

a % b

a.__mod__(b)

Listing 120. Modulo operator for int and str
7 % 2                   # 1
'My number' % 2         # TypeError: not all arguments converted during string formatting
'My number %s' % 2      # My number 2
'My number %d' % 2      # My number 2
'My number %f' % 2      # My number 2.0

Note

%s, %d, %f is currently deprecated in favor of f'...' string formatting. The topic will be continued in Builtin Printing chapter.

10.7.2.2. Comparison Operators

Table 21. Comparison Operators Overload

Operator

Method

a == b

a.__eq__(b)

a != b

a.__ne__(b)

a < b

a.__lt__(b)

a <= b

a.__le__(b)

a > b

a.__gt__(b)

a >= b

a.__ge__(b)

10.7.2.3. Boolean Operators

Table 22. Boolean Operators Overload

Operator

Method

-a

a.__neg__(b)

+a

a.__pos__(b)

a & b

a.__and__(b)

a | b

a.__or__(b)

a ^ b

a.__xor__(b)

a << b

a.__lshift__(b)

a >> b

a.__rshift__(b)

10.7.2.4. Builtin Functions and Keywords

Table 23. Builtin Functions Overload

Function

Method

abs(a)

a.__abs__()

bool(a)

a.__bool__()

divmod(a, b)

a.__divmod__(b)

pow(a)

a.__pow__()

round(a, prec)

a.__round__(prec)

dir(a)

a.__dir__()

len(a)

a.__len__()

complex(a)

a.__complex__()

int(a)

a.__int__()

float(a)

a.__float__()

oct(a)

a.__oct__()

hex(a)

a.__hex__()

reversed(a)

a.__reversed__()

delattr(a, attr)

a.__delattr__(attr)

del a

a.__del__()

from math import sqrt


class Vector:
    def __init__(self, x=0, y=0):
        self.x = x
        self.y = y

    def __abs__(self):
        return sqrt(self.x**2 + self.y**2)


vector = Vector(x=3, y=4)
abs(vector)
# 5.0

10.7.2.5. Accessors Overload

Table 24. Operator Overload

Operator

Method

Description

a(b)

a.__call__(b)

a[b] = 10

a.__setitem__(b, 10)

a[b]

a.__getitem__(b)

b in a

a.__contains__(b)

a[b]

a.__missing__(b)

(when b is not in a)

Listing 121. Contains in numpy
import numpy as np

a = np.array([[1, 2, 3],
              [4, 5, 6]])

a[1][2]  # 6
a[1,2]   # 6
Listing 122. Intuitive implementation of numpy array[row,col] accessor
class array(list):
    def __getitem__(key):
        row = key[0]
        col = key[1]
        return super().__getitem__(row).__getitem__(col)

# a[1,2]
a.__getitem__(key=(1,2))

10.7.3. Assignment

10.7.3.1. Address Book

English
  1. Use the code from listing below

  2. Override operators of Astronaut and Location for code to work correctly

Polish
  1. Użyj kodu z listingu poniżej

  2. Nadpisz operatory Astronaut i Location aby poniższy kod zadziałał poprawnie

class Astronaut:
    def __str__(self):
        return f'{self.name}, {self.locations}'


class Location:
    def __repr__(self):
        return f'\n\t{self.name}'


astro = Astronaut('Jan Twardowski', locations=[
    Location('Armstrong Flight Research Center'),
    Location('Kennedy Space Center'),
])

astro += Location('Jet Propulsion Laboratory')
astro += Location('Johnson Space Center')

print(astro)
# Jan Twardowski, [
#     Armstrong Flight Research Center,
#     Kennedy Space Center,
#     Jet Propulsion Laboratory,
#     Johnson Space Center]

if Location('Johnson Space Center') in astro:
    print(True)
else:
    print(False)
# True