Ted.Magnito
Ted.Magnito

Reputation: 81

__add__ two class objects

I've been learning Python 2 by searching for tutorials. I'm discovering things about class. I have some trouble in __add__ dunder-method. I don't know how to add 2 objects of a class.

To be clearer:

class Add_obj:
    def __init__(self, *num):
        self.num = num

    def __repr__(self):
        return 'Add_obj{}'.format(self.num)

    def __add__(self, other):
        for i in zip(*(self.num + other.num)):
            # and then some codes over here

#when:
obj1 = Add_obj(2, 5)
obj2 = Add_obj(4, 7)
# it should return Add_obj(6, 12)

I know it's not the best way to add 2 objects?

Upvotes: 8

Views: 8019

Answers (2)

MSeifert
MSeifert

Reputation: 152647

You could use map with operator.add and iterable unpacking (using *) in __add__. For example:

import operator

class Add_obj:
    def __init__(self, *num):
        self.num = num

    def __repr__(self):
        return 'Add_obj{}'.format(self.num)

    def __add__(self, other):
        return self.__class__(*map(operator.add, self.num, other.num))

And it indeed returns the "expected object":

>>> obj1 = Add_obj(2, 5)
>>> obj2 = Add_obj(4, 7)
>>> obj1 + obj2
Add_obj(6, 12)

However map is not really required it's just a very performant and short way to accomplish this. You could also use a comprehension and zip instead:

def __add__(self, other):
    return self.__class__(*[num1+num2 for num1, num2 in zip(self.num, other.num)])

As pointed out in the comments this will also work, but possibly give unexpected (or even wrong) results when the two Add_obj have different lengths. If you want to prohibit adding two different sized objects you could raise an Exception instead:

def __add__(self, other):
    if len(self.num) != len(other.num):
        raise ValueError('cannot two Add_obj with different lengths')
    ...  # use one of the both approaches from above

For example:

>>> obj1 = Add_obj(2, 5)
>>> obj2 = Add_obj(4, 7, 2)
>>> obj1 + obj2
ValueError: cannot two Add_obj with different lengths

Or you could zero-pad the shorter one:

from itertools import izip_longest as zip_longest  # only zip_longest on Python 3

class Add_obj:

    ...

    def __add__(self, other):
        return self.__class__(*[num1+num2 for num1, num2 in zip_longest(self.num, other.num, fillvalue=0)])

For example:

>>> obj1 = Add_obj(2, 5)
>>> obj2 = Add_obj(4, 7, 2)
>>> obj1 + obj2
Add_obj(6, 12, 2)

Upvotes: 4

Richard Neumann
Richard Neumann

Reputation: 3361

Using zip was a good idea.

class Add_obj:
    def __init__(self, *num):
        self.num = num

    def __repr__(self):
        return 'Add_obj{}'.format(self.num)

    def __add__(self, other):
        return Add_obj(*(sum(pair) for pair in zip(self.num, other.num)))


obj1 = Add_obj(2, 5)
obj2 = Add_obj(4, 7)
obj3 = obj1 + obj2

print(obj1)
print(obj2)
print(obj3)

Upvotes: 1

Related Questions