Python Operator Overloading

You can change the meaning of an operator in Python depending upon the operands used. In this tutorial, you will learn how to use operator overloading in Python Object Oriented Programming.

Python Operator Overloading

Python operators work for built-in classes. But the same operator behaves differently with different types. For example, the + operator will perform arithmetic addition on two numbers, merge two lists, or concatenate two strings.

This feature in Python that allows the same operator to have different meaning according to the context is called operator overloading.

So what happens when we use them with objects of a user-defined class? Let us consider the following class, which tries to simulate a point in 2-D coordinate system.

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


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

Output

Traceback (most recent call last):
  File "<string>", line 9, in <module>
    print(p1+p2)
TypeError: unsupported operand type(s) for +: 'Point' and 'Point'

Here, we can see that a TypeError was raised, since Python didn’t know how to add two Point objects together.

However, we can achieve this task in Python through operator overloading. But first, let’s get a notion about special functions.


Python Special Functions

Class functions that begin with double underscore __ are called special functions in Python.

These functions are not the typical functions that we define for a class. The __init__() function we defined above is one of them. It gets called every time we create a new object of that class.

There are numerous other special functions in Python. Visit Python Special Functions to learn more about them.

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

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

Suppose we want the print() function to print the coordinates of the Point object instead of what we got. We can define a __str__() method in our class that controls how the object gets printed. Let’s look at how we can achieve this:

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 print() function again.

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)


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

Output

(2, 3)

That’s better. Turns out, that this same method is invoked when we use the built-in function str() or format().

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

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

So, when you use str(p1) or format(p1), Python internally calls the p1.__str__() method. Hence the name, special functions.

Now let’s go back to operator overloading.


Overloading the + Operator

To overload the + operator, we will need to implement __add__() function in the class. With great power comes great responsibility. We can do whatever we like, inside this function. But it is more sensible to return a Point object of the coordinate sum.

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 the addition operation again:

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)


p1 = Point(1, 2)
p2 = Point(2, 3)

print(p1+p2)

Output

(3,5)

What actually happens is that, when you use p1 + p2, Python calls p1.__add__(p2) which in turn is Point.__add__(p1,p2). After this, the addition operation is carried out the way we specified.

Similarly, we can overload other operators as well. The special function that we need to implement is tabulated below.

OperatorExpressionInternally
Additionp1 + p2p1.__add__(p2)
Subtractionp1 - p2p1.__sub__(p2)
Multiplicationp1 * p2p1.__mul__(p2)
Powerp1 ** p2p1.__pow__(p2)
Divisionp1 / p2p1.__truediv__(p2)
Floor Divisionp1 // p2p1.__floordiv__(p2)
Remainder (modulo)p1 % p2p1.__mod__(p2)
Bitwise Left Shiftp1 << p2p1.__lshift__(p2)
Bitwise Right Shiftp1 >> p2p1.__rshift__(p2)
Bitwise ANDp1 & p2p1.__and__(p2)
Bitwise ORp1 | p2p1.__or__(p2)
Bitwise XORp1 ^ p2p1.__xor__(p2)
Bitwise NOT~p1p1.__invert__()

Overloading Comparison Operators

Python does not limit operator overloading to arithmetic operators only. We can overload comparison operators as well.

Suppose we wanted to implement the less than symbol < symbol in our Point class.

Let us compare the magnitude of these points from the origin and return the result for this purpose. It can be implemented as follows.

# overloading the less than operator
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

p1 = Point(1,1)
p2 = Point(-2,-3)
p3 = Point(1,-1)

# use less than
print(p1<p2)
print(p2<p3)
print(p1<p3)

Output

True
False
False

Similarly, the special functions that we need to implement, to overload other comparison operators are tabulated below.

OperatorExpressionInternally
Less thanp1 < p2p1.__lt__(p2)
Less than or equal top1 <= p2p1.__le__(p2)
Equal top1 == p2p1.__eq__(p2)
Not equal top1 != p2p1.__ne__(p2)
Greater thanp1 > p2p1.__gt__(p2)
Greater than or equal top1 >= p2p1.__ge__(p2)

C++ Operator Overloading

In C++, it’s possible to change the way operator works (for user-defined types). In this article, you will learn to implement operator overloading feature.

The meaning of an operator is always same for variable of basic types like: int, float, double etc. For example: To add two integers, + operator is used.

However, for user-defined types (like: objects), you can redefine the way operator works. For example:

If there are two objects of a class that contains string as its data members. You can redefine the meaning of + operator and use it to concatenate those strings.

This feature in C++ programming that allows programmer to redefine the meaning of an operator (when they operate on class objects) is known as operator overloading.


Why is operator overloading used?

You can write any C++ program without the knowledge of operator overloading. However, operator operating are profoundly used by programmers to make program intuitive. For example,

You can replace the code like:

calculation = add(multiply(a, b),divide(a, b));

to

calculation = (a*b)+(a/b);

How to overload operators in C++ programming?

To overload an operator, a special operator function is defined inside the class as:

class className
{
    ... .. ...
    public
       returnType operator symbol (arguments)
       {
           ... .. ...
       } 
    ... .. ...
};
  • Here, returnType is the return type of the function.
  • The returnType of the function is followed by operator keyword.
  • Symbol is the operator symbol you want to overload. Like: +, <, -, ++
  • You can pass arguments to the operator function in similar way as functions.

Example: Operator overloading in C++ Programming

#include <iostream>
using namespace std;

class Test
{
   private:
      int count;

   public:
       Test(): count(5){}

       void operator ++() 
       { 
          count = count+1; 
       }
       void Display() { cout<<"Count: "<<count; }
};

int main()
{
    Test t;
    // this calls "function void operator ++()" function
    ++t;    
    t.Display();
    return 0;
}

Output

Count: 6

This function is called when ++ operator operates on the object of Test class (object t in this case).

In the program,void operator ++ () operator function is defined (inside Test class).

This function increments the value of count by 1 for t object.


Things to remember

  1. Operator overloading allows you to redefine the way operator works for user-defined types only (objects, structures). It cannot be used for built-in types (int, float, char etc.).
  2. Two operators = and & are already overloaded by default in C++. For example: To copy objects of same class, you can directly use = operator. You do not need to create an operator function.
  3. Operator overloading cannot change the precedence and associatively of operators. However, if you want to change the order of evaluation, parenthesis should be used.
  4. There are 4 operators that cannot be overloaded in C++. They are :: (scope resolution), . (member selection), .* (member selection through pointer to function) and ?: (ternary operator).

Following best practices while using operator overloading

Operator overloading allows you to define the way operator works (the way you want).

In the above example, ++ operator operates on object to increase the value of data member count by 1.

void operator ++() 
    { 
        count = count+1; 
    }

However, if you use the following code. It decreases the value of count by 100 when ++ operator is used.

void operator ++() 
    { 
        count = count-100; 
    }

This may be technically correct. But, this code is confusing and, difficult to understand and debug.

It’s your job as a programmer to use operator overloading properly and in consistent way.


In the above example, the value of count increases by 1 when ++ operator is used. However, this program is incomplete in sense that you cannot use code like:

t1 = ++t

It is because the return type of the operator function is void.