Python __add__() Method

The __add__() method in Python specifies what happens when you call + on two objects. When you call obj1 + obj2, you are essentially calling obj1.__add__(obj2).

For example, let’s call + on two int objects:

n1 = 10
n2 = 20

print(n1 + n2)
print(n1.__add__(n2))

Output:

30
30

This works, because int implements the __add__() method behind the scenes.

To make a custom object support addition with + operator, you need to implement the __add__() method in the class.

In this guide, you learn how to implement the __add__() method. You also learn how to add objects of mixed types. Finally, you are going to see how to make adding mixed types of objects commutative (a + b = b + a).

Double Underscore Methods in Python

In case you are new to the double underscore methods, here is a quick summary.

In Python, double-underscore methods (also known as dunder methods) make operator overloading possible.

A dunder method is implemented into a class to define the behavior for what happens when a specific operation is called on an object.

A common example of a dunder method is the __init__ method. This method is automatically called when an object is created.

For example:

class Fruit:
    def __init__(self, name):
        self.name = name

# This calls __init__ with "Apple" argument:
apple = Fruit("Apple")

print(banana.name) # prints "Apple"

The __add__() Method in Python

The __add__() method in Python is a special method that defines what happens when you add two objects with the + operator. When you call o1 + o2, under the hood you are calling o1.__add__(o2).

Let’s see a demonstrative example by creating a class Weight:

class Weight:
    def __init__(self, kilos):
        self.kilos = kilos

Now, let’s create two Weight objects and try to add them together:

w1 = Weight(50)
w2 = Weight(150)

tot = w1 + w2

Output:

TypeError: unsupported operand type(s) for +: 'Weight' and 'Weight'

This error says Weight objects do not support addition with + operator. The reason why this fails is that you have not specified what should happen when calling + on two Weight objects.

To define what happens when adding weights, you need to implement the __add__() method in the Weight class.

In this example, adding two Weight objects should produce a new Weight object whose kilos is the sum of the kilos of the two Weight objects.

Here is how it looks in code:

class Weight:
    def __init__(self, kilos):
        self.kilos = kilos
    
    def __add__(self, otherWeight):
        return Weight(self.kilos + otherWeight.kilos)
  • The __add__() method takes self as a parameter to know its own weight. When calling w1 + w2, self refers to w1.
  • The __add__() method also takes otherWeight parameter to get the weight of the second Weight object. The otherWeight is the same as w2 when calling w1 + w2.
Two weight objects illustrate how to use self in Python

Now you can add two Weight objects together by:

w1 = Weight(50)
w2 = Weight(150)

tot = w1 + w2

print(tot.kilos)

Output:

200

Notice how calling w1 + w2 is the exact same as calling w1.__add__(w2).

For example:

w1 = Weight(50)
w2 = Weight(150)

tot = w1.__add__(w2)

print(tot.kilos)

Output:

200

By the way, now you can also call the + operator on multiple Weights:

w1 = Weight(50)
w2 = Weight(150)
w3 = Weight(25)

tot = w1 + w2 + w3

Output:

225

But why does it work?

This boils down to operator precedence. When you are summing up three integers, Python first sums the two and then adds the third to that sum.

In other words, the Python interpreter first sums up w1 + w2. The result of this is an integer object to which w3 is added. So behind the scenes w1 + w2 + w3 looks like this:

tot = (w1.__add__(w2)).__add__(w3)

Feel free to try it out on your editor. Also, feel free to extend the chain to understand how it works.

Adding Different Types of Objects Together

So far you’ve seen how to add Weight objects together.

But let’s say you also want to add ints and weights.

Supporting this is easy. Modify the __add__() method so that it checks the type of the other object.

  • If the type is int, then create a new Weight object from the original weight’s kilos by adding the integer value to it.
  • If the type is Weight, add the kilos of both objects together and create a new Weight out of that.

Here is how it looks in code:

class Weight:
    def __init__(self, kilos):
        self.kilos = kilos
    
    def __add__(self, otherWeight):
        if type(otherWeight) == int:
            return Weight(self.kilos + otherWeight)
        else:
            return Weight(self.kilos + otherWeight.kilos)

Now you can add Weight objects and ints:

w1 = Weight(100)
total = w1 + 200

print(total.kilos)

Output:

300

But as you know, summing up two values in mathematics is commutative. In other words, a+b is b+a. Let’s see what happens when we try to reverse the order of addition:

w1 = Weight(100)
total = 200 + w1

print(total.kilos)

Output:

TypeError: unsupported operand type(s) for +: 'int' and 'Weight'

This fails because now you are trying to call (200).__add__(w1). In other words, you assume that int also supports adding Weight objects to it, which is obviously not true.

This is where the __radd__() method helps.

The __radd__() Method in Python

Now that you know what the __add__() method does, it is good to know what the __radd__() does, as it closely relates to the __add__() method.

The __radd__() method means reverse add.

The reverse add flips a + b to b + a. This means a.__add__(b) turns into b.__radd__(a).

But why?

Let’s demonstrate the problem this solves with the Weight class from the previous chapter.

As you already saw, adding an integer and Weight object in this order fails:

w1 = Weight(50)

total = 150 + w1

This results in the following error:

TypeError: unsupported operand type(s) for +: 'int' and 'Weight'

The error says it is not possible to add int and Weight together. This is not surprising, as the built-in int type does not know anything about Weight.

A square plus a circle is ??? because you can't add two different types into one another

As you now know, calling 150 + w1 is equivalent to (150).__add__(w1). So under the hood, calling (150).__add__(w1) causes the problem.

To fix the problem, it is not an option to make int support adding Weight objects. But what you can do instead, is to make the Weight object support adding ints.

In other words, you want to swap calls like this:

(150).__add__(w1)

With this:

w1.__add__(150)

This is what the __radd__() method does. It reverses the addition order. In other words, a.__add__(b) becomes b.__radd__(a).

So, let’s implement the __radd__() method into the Weight class. This should return a Weight object where an integer is added to the kilos:

class Weight:
    def __init__(self, kilos):
        self.kilos = kilos
    
    def __add__(self, otherWeight):
        if type(otherWeight) == int:
            return Weight(self.kilos + otherWeight)
        else:
            return Weight(self.kilos + otherWeight.kilos)
    
    def __radd__(self, kilos_int):
        return Weight(self.kilos + kilos_int)

Now the previously erroneous code runs successfully:

w1 = Weight(50)

total = 150 + w1
print(total.kilos)

Output:

200

Now you know how the __radd__() method works and when it can be useful.

To be exact, you could also use the __add__() method in the __radd__() method as it knows how to handle integer inputs. This simplifies the code a bit:

class Weight:
    def __init__(self, kilos):
        self.kilos = kilos
    
    def __add__(self, otherWeight):
        if type(otherWeight) == int:
            return Weight(self.kilos + otherWeight)
        else:
            return Weight(self.kilos + otherWeight.kilos)
    
    def __radd__(self, kilos_int):
        return self.__add__(kilos_int)

Anyway, supporting __radd__() makes the code consistent. Now both a + b and b + a work as expected.

By the way, now that the Weight class supports __radd__() it is also possible to call the sum() on a list of Weight objects.

For example:

w1 = Weight(100)
w2 = Weight(150)
w3 = Weight(220)

total = sum([w1, w2, w3])

print(total.kilos)

Output:

470

Without __radd__() this would not be possible. This is because the built-in sum() function starts summing from 0. This means the first operation would be (0).__add__(w1), which would not work without the reverse add implementation that turns it into w1.__radd__(0).

Conclusion

Today you learned what the __add__() method is in Python and how to use it.

To recap, whenever you call obj1 + obj2 in Python, you are truly calling obj1.__add__(obj2) behind the scenes.

In other words, to add two objects together in Python, the class implementing the objects needs to implement the __add__() method.

Another related method is the __radd__() method. This flips a+b with b+a. When a.__add__(b) fails, the call becomes b.__radd__(a). This is useful when the a does not support adding b, but b can be made to support adding a.

Thanks for reading.

Happy coding!

Further Reading

50 Python Interview Questions