Python Operator Overloading
Operator overloading is the process of defining a special behavior for built-in operators such as +
, -
, *
, /
, %
, ==
, !=
, <
, >
, <=
, >=
, and
, or
, and others when they are used with objects of user-defined classes. This allows us to use these operators with our own custom objects in a way that is natural and intuitive.
In Python, operator overloading is achieved by defining special methods in the class that correspond to the operator being overloaded. These methods are called magic methods or dunder methods (short for "double underscore" methods) because their names are enclosed in double underscores.
For example, let's say we have a class Fraction
that represents a fraction with a numerator and denominator. We can define the +
operator to add two fractions together by defining the __add__
method:
class Fraction: def __init__(self, numerator, denominator): self.numerator = numerator self.denominator = denominator def __add__(self, other): new_numerator = self.numerator * other.denominator + self.denominator * other.numerator new_denominator = self.denominator * other.denominator return Fraction(new_numerator, new_denominator)
In this example, we've defined the __add__
method to take two Fraction
objects as arguments and return a new Fraction
object that represents their sum. When we use the +
operator with two Fraction
objects, Python will automatically call this method.
We can create two Fraction
objects and add them together using the +
operator:
a = Fraction(1, 2) b = Fraction(3, 4) c = a + b print(c.numerator, c.denominator) # Output: 5 4
When we add a
and b
together with the +
operator, Python calls the __add__
method that we defined in the Fraction
class, which returns a new Fraction
object with the sum of the two fractions. The output of the program is 5 4
, which represents the fraction 5/4
.
Python provides many other magic methods for operator overloading, such as __sub__
for the -
operator, __mul__
for the *
operator, __eq__
for the ==
operator, and many more. By defining these methods in our own classes, we can customize the behavior of built-in operators to work with our custom objects.