tags:

views:

969

answers:

5

Is there a simple and quick way to use sum() with non-integer values?

So I can use it like this:

class Foo(object):
    def __init__(self,bar)
        self.bar=bar

mylist=[Foo(3),Foo(34),Foo(63),200]
result=sum(mylist) # result should be 300

I tried overriding __add__ and __int__ etc, but I don't have found a solution yet

EDIT:

The solution is to implement:

 def __radd__(self, other):
    return other + self.bar

as Will suggested in his post. But as always, all roads lead to Rome, but I think this is the best solution since I don't need __add__ in my class

+2  A: 

Try:

import operator
result=reduce(operator.add, mylist)

sum() works probably faster, but it is specialized for builtin numbers only. Of course you still have to provide a method to add your Foo() objects. So full example:

class Foo(object):
    def __init__(self, i): self.i = i
    def __add__(self, other):
        if isinstance(other, int):
            return Foo(self.i + other)
        return Foo(self.i + other.i)
    def __radd__(self, other):
        return self.__add__(other)

import operator
mylist = [Foo(42), Foo(36), Foo(12), 177, Foo(11)]
print reduce(operator.add, mylist).i
liori
+3  A: 

Try using the __int__ method and then mapping each element in your list to the int function to get the values out:

class Foo(object):
    def __init__(self,bar):
     self.bar = bar
    def __int__(self):
     return self.bar

mylist = [Foo(3),Foo(34),Foo(63),200]
result = sum(map(int,mylist))
print(result)
Andrew Hare
+1  A: 

Or if you don't want to import anything,

result=reduce( (lambda x,y:x+y), mylist

Another small advantage is that you don't have to necessarily declare an add method as part of your Foo objects, if this happens to be the only circumstance in which you'd want to do addition. (But it probably wouldn't hurt to define add for future flexibility.)

Amber
+7  A: 

You may also need to implement the __radd__ function, which represents "reverse add" and is called when the arguments can't be resolved in the "forward" direction. For example, x + y is evaluated as x.__add__(y) if possible, but if that doesn't exist then Python tries y.__radd__(x).

Since the sum() function starts with the integer 0, the first thing it does is try to evaluate:

0 + Foo(3)

which will require that you implement Foo.__radd__.

Greg Hewgill
+6  A: 

Its a bit tricky - the sum() function takes the start and adds it to the next and so on

You need to implement the __radd__ method:

class T:
    def __init__(self,x):
     self.x = x
    def __radd__(self, other):
     return other + self.x

test = (T(1),T(2),T(3),200)
print sum(test)
Will
I think just implementing __radd__ is the best solution, since it doesn't need map(), reduce() or importing additional modules.
dkson