in , ,

Python Operator Overloading

Python Operator Overloading

Python Operator Overloading. You can change the significance of an operator in Python relying on 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. Be that as it may, a similar administrator acts contrastingly with various sorts. For instance, the + operator will perform number-crunching expansion on two numbers, combine two lists, or concatenate two strings.

This element in Python that permits a similar administrator to have distinctive significance as per the setting is called administrator over-burdening.

So what happens when we use them with objects of a client characterized class? Let us think about the accompanying class, which attempts to mimic a point in the 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 an __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 the __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 thus is Point.__add__(p1,p2). After this, the expansion activity has completed the manner in which we indicated.

So also, we can overload different 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 doesn’t limit operator overloading to arithmetic operators only. We can overload comparison operators as well.

Assume we needed to actualize the not as much as image < 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)

Please feel free to give your comment if you face any difficulty here.

For more Articles click on the below link.

salman khan

Written by worldofitech

Leave a Reply

Python Iterators

Python Iterators

Python Generators

Python Generators