Search code examples
pythonpython-3.xclassinstance-variables

How to correctly perform arithmetic on classes instances? E.g. Sum the n_people attribute for a list of House class instances


How to correctly perform arithmetic on classes instances? In the below example the class represents a House and contains an n_people attribute representing the number of people in that house.

The objective is to perform a sum on the House class instances and return the total number of people in the houses. This seems to work when the House class instances are added together:

class House:

    def __init__(self, n_people):
        self.n_people = n_people

    def __add__(self, n_people):
        return n_people + self.n_people

House(3) + House(4)

And fails when an array of House class instances is being summed:

houses = [House(i) for i in range(10)]
sum(houses)

The resulting error is:

TypeError                                 Traceback (most recent call last)
<ipython-input-66-197f26932b89> in <module>
      1 houses = [House(i) for i in range(10)]
----> 2 sum(houses)

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

What is the correct way to perform arithmetic on class instances in Python?


Solution

  • The problem you're facing is that sum works left-to-right, so after the first two House instances are summed, your code tries to perform int + House, when only House + int is defined.

    To solve this, you need to define __radd__, which gets called in that situation:

    class House:
    
        def __init__(self, n_people):
            self.n_people = n_people
    
        def __add__(self, n_people):
            return n_people + self.n_people
    
        def __radd__(self, n_people):
            return n_people + self.n_people
    
    House(3) + House(4)
    houses = [House(i) for i in range(10)]
    sum(houses)
    

    Output:

    45