Python: Sum up list of objects

Question:

I am working with a number of custom classes X that have __add__(self), and when added together return another class, Y.

I often have iterables [of various sizes] of X, ex = [X1, X2, X3] that I would love to add together to get Y. However, sum(ex) throws an int error, because sum starts at 0 which can’t be added to my class X.

Can someone please help me with an easy, pythonic way to do X1 + X2 + X3 ... of an interable, so I get Y

Thanks!

Ps it’s a 3rd party class, X, so I can’t change it. It does have radd though.

My gut was that there was some way to do list comprehension? Like += on themselves

Asked By: keynesiancross

||

Answers:

You can specify the starting point for a sum by passing it as a parameter. For example, sum([1,2,3], 10) produces 16 (10 + 1 + 2 + 3), and sum([[1], [2], [3]], []) produces [1,2,3].

So if you pass an appropriate ("zero-like") X object as the second parameter to your sum, ie sum([x1, x2, x3,...], x0) you should get the results you’re looking for

Some example code, per request. Given the following definitions:

class X:                                                                                                                                                                                                                                      
    def __init__(self, val):                                                                                                                                                                                                                  
        self.val = val                                                                                                                                                                                                                        
    def __add__(self, other):
        return X(self.val + other.val)                                                                                                                                                                                                        
                                                                                                                                                                                                                                              
    def __repr__(self):                                                                                                                                                                                                                       
        return "X({})".format(self.val)                                                                                                                                                                                                       
                                                                                                                                                                                                                                              
class Y:                                                                                                                                                                                                                                      
    def __init__(self, val):                                                                                                                                                                                                                  
        self.val = val                                                                                                                                                                                                                        
    def __add__(self, other):
        return X(self.val + other.val)                                                                                                                                                                                                        
                                                                                                                                                                                                                                              
    def __repr__(self):                                                                                                                                                                                                                       
        return "Y({})".format(self.val)                                                                                                                                                                                                       

I get the following results:

>>> sum([Y(1), Y(2), Y(3)], Y(0))
X(6)
>>> sum([Y(1), Y(2), Y(3)], Y(0))
X(6)
>>>

(note that Y returns an X object – but that the two objects’ add methods are compatible, which may not be the case in the OP’s situation)

Answered By: Jon Kiparsky

Assuming that you can add an X to a Y (i.e. __add__ is defined for Y and accepts an object of class X), then you can use
reduce from functools, a generic way to apply an operation to a number of objects, either with or without a start value.

from functools import reduce

xes = [x1, x2, x3]
y = reduce(lambda a,b: a+b, xes)
Answered By: treuss

What if you did something like:

Y = [ex[0]=+X for x in ex[1:]][0]

I haven’t tested it yet though, on mobile

Answered By: keynesiancross
Categories: questions Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.