English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Python Basic Tutorial

Python Flow Control

Python Functions

Python Data Types

Python File Operations

Python Objects and Classes

Python Date and Time

Advanced Knowledge of Python

Python Reference Manual

Python Operator Overloading

You can change the meaning of operators in Python based on the operands you use. This practice is called operator overloading.

What is operator overloading in Python?

Python operatorsFor built-in classes. But the same operator has different behaviors for different types. For example,+The operator will perform arithmetic addition on two numbers, merge two lists, and connect two strings.

This feature in Python allows the same operator to have different meanings according to the context, which is called operator overloading.

So, what happens when we use them with objects of user-defined classes? Let's look at the following class, which tries to simulate a point in a two-dimensional coordinate system.

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

Now, run the code and try to add two points in the Python shell.

>>> p1 = Point(2,3)
>>> p2 = Point(-1,2)
>>> p1 + p2
Traceback (most recent call last):
...
TypeError: unsupported operand type(s) for +: 'Point' and 'Point'

Wow! There are many errors. TypeError is raised because Python does not know how to add two Point objects together.

The good news is that we can teach Python this through operator overloading. But first, let's understand what special functions are.

Special functions in Python

Class functions that start with double underscores __ are called special functions in Python. This is because they are not ordinary functions. The __init__() function we defined above is one of them. It is called every time we create a new object of the class. There are many special functions in Python.

Using special functions, we can make our class compatible with built-in functions.

>>> p1 = Point(2,3)
>>> print(p1)
<__main__.Point object at 0x00000000031F8CC0>

The print output did not reach the expected effect. But if we define the __str__() method in the class, we can control its print output. We add this to our class.

class Point:
    def __init__(self, x = 0, y = 0):
        self.x = x
        self.y = y
    
    def __str__(self):
        return "({0},"1})".format(self.x, self.y)

Now, let's try the function again with print().

>>> p1 = Point(2,3)
>>> print(p1)
(2,3)

 It turns out that it is better when we use the built-in functions str() or format() because they call the same method format().

>>> str(p1)
'('2,3)
>>> format(p1)
'('2,3)

Therefore, when you execute str(p1) or format(p1) is executed, Python internally executes p1.__str__() is called, which is why it is called a special function. Let's continue with operator overloading.

Operator overloading in Python+operator

to overload+With the right to overload, we are also given great responsibility. We can do anything we like in this function. But it is wise to return a Point object with the sum of coordinates. We can implement the __add__() function in the class. Having the right also means being given great responsibility. We can do anything we like in this function. But it is wise to return a Point object with the sum of coordinates.

class Point:
    def __init__(self, x = 0, y = 0):
        self.x = x
        self.y = y
    
    def __str__(self):
        return "({0},"1})".format(self.x, self.y)
    
    def __add__(self, other):
        x = self.x + other.x
        y = self.y + other.y
        return Point(x, y)

Now, let's try again.

>>> p1 = Point(2,3)
>>> p2 = Point(-1,2)
>>> print(p1 + p2)
(1,5)

What actually happens is, when you execute p1 + p2when Python will call p1 __ add __(p2) which is also Point.__ add __(p1, p2). Similarly, we can overload other operators. The list of special functions we need to implement is as follows.

Special functions for operator overloading in Python
operatorexpressionInternally
Addition (+)p1 + p2p1 __ add __(p2)
Subtraction (-)p1-p2p1 __ sub __(p2)
Multiplication (*)p1 * p2p1 __ mul __(p2)
Power (**)p1 ** p2p1 __ pow __(p2)
Division (/)p1 / p2p1 __ truediv __(p2)
Floor division (//)
p1 // p2p1 __ floordiv __(p2)
Modulus (%)p1%p2p1 __ mod __(p2)
Bitwise left shift (<<)p1 << p2p1 __ lshift __(p2)
Bitwise right shift (>>)p1 >> p2p1 __ rshift __(p2)
Bitwise AND (and)p1 and p2p1 .__ and __ (p2)
Bitwise OR (or)p1 | 2p1 .__ or __ (p2)
Bitwise XOR (^)p1 ^ p2p1 .__ xor __ (p2)
Bitwise NOT(~)~p1p1 .__ invert __ ()

Operator overloading in Python

Python does not limit operator overloading to arithmetic operators. We can also overload comparison operators.

Suppose, we want to implement the less than operator (<) in the Point class. Let's compare the sizes of these points from the origin and return the result for this purpose. It can be implemented as follows.

class Point:
    def __init__(self, x = 0, y = 0):
        self.x = x
        self.y = y
    
    def __str__(self):
        return "({0},"1})".format(self.x, self.y)
    
    def __lt__(self, other):
        self_mag = (self.x ** 2) + (self.y ** 2)
        other_mag = (other.x ** 2) + (other.y ** 2)
        return self_mag < other_mag

Try running these examples in the Python shell.

>>  Point(1,1)  <  Point(-2,-3)
True
>>  Point(1,1)  <  Point(0.5,-0.2)
False
>>  Point(1,1)  <  Point(1,1)
False

Similarly, the following lists the special functions that we need to implement to overload other comparison operators.

Operator overloading for comparison operators in Python
operator
expressionInternal
Less than (<)p1 <p2p1 .__ lt __ (p2)
Less than or equal to (<=)p1 <= p2p1 .__ le __ (p2)

Equal to (==)

p1 == p2p1 .__ eq __ (p2)
Not equal to (!=)p1!= p2p1 .__ ne __ (p2)
Greater than (>)p1> p2p1 .__ gt __ (p2)
Greater than or equal to (>=)p1>= p2p1 .__ ge __ (p2)