Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TypeError after overriding the __add__ method

Tags:

python

I am trying to understand how __add__ works:

class MyNum:     def __init__(self,num):         self.num=num     def __add__(self,other):         return MyNum(self.num+other.num)     def __str__(self):         return str(self.num) 

If I put them in a list

d=[MyNum(i) for i in range(10)] 

this works

t=MyNum(0) for n in d:     t=t+n print t 

But this does not:

print sum(d) TypeError: unsupported operand type(s) for +: 'int' and 'instance' 

What am I doing wrong? How can I get the sum() to work?

My problem is how to use the sum on a list of objects that support the __add__, need to keep it as generic as possible.

like image 652
Ηλίας Avatar asked Feb 22 '11 18:02

Ηλίας


People also ask

What is __ add __ method in Python?

__add__ magic method is used to add the attributes of the class instance. For example, let's say object1 is an instance of a class A and object2 is an instance of class B and both of these classes have an attribute called 'a', that holds an integer.

What is __ Radd __ in Python?

The Python __radd__() method implements the reverse addition operation that is addition with reflected, swapped operands. So, when you call x + y , Python attempts to call x.


2 Answers

You need to define __radd__ as well to get this to work.

__radd__ is reverse add. When Python tries to evaluate x + y it first attempts to call x.__add__(y). If this fails then it falls back to y.__radd__(x).

This allows you to override addition by only touching one class. Consider for example how Python would have to evaluate 0 + x. A call to 0.__add__(x) is attempted but int knows nothing about your class. You can't very well change the __add__ method in int, hence the need for __radd__. I suppose it is a form of dependency inversion.

As Steven pointed out, sum operates in place, but starts from 0. So the very first addition is the only one that would need to use __radd__. As a nice exercise you could check that this was the case!

like image 166
David Heffernan Avatar answered Oct 02 '22 20:10

David Heffernan


>>> help(sum) Help on built-in function sum in module __builtin__:  sum(...)     sum(sequence[, start]) -> value      Returns the sum of a sequence of numbers (NOT strings) plus the value     of parameter 'start' (which defaults to 0).  When the sequence is     empty, returns start. 

In other words, provide a start value:

sum(d, MyNum(0)) 

Edit pasted from my below comment:

sum works with a default start value of the integer zero. Your MyNum class as written does not know how to add itself to integers. To solve this you have two options. Either you can provide a start value to sum that has the same type as you class, or you can implement __radd__, which Python calls when adding values of differing types (such as when the first value in d is added to the default start value of zero).

like image 40
Steven Rumbalski Avatar answered Oct 02 '22 18:10

Steven Rumbalski