6

I am trying to understand the working of the built-in sum() function, but, the start parameter has evaporated my mind:

  1. a=[[1, 20], [2, 3]]
    b=[[[[[[1], 2], 3], 4], 5], 6]
    >>> sum(b,a)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: can only concatenate list (not "int") to list
    >>> sum(a,b)
    [[[[[[1], 2], 3], 4], 5], 6, 1, 20, 2, 3]
    
  2. >>> a=[1,2]
    >>> b=[3,4]
    >>> sum(a,b)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: can only concatenate list (not "int") to list
    >>> sum(b,a)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: can only concatenate list (not "int") to list
    

I am just dumbfounded by this and don't have any idea what is happening. Here is what the python docs have to say: http://docs.python.org/library/functions.html#sum. This does not give any explanation on 'what if the start is not a string and not an integer?'

2
  • I use start argument only for cumulative sums and so type is only int. I don't think it's intended for such pathological cases :) Commented Aug 30, 2012 at 17:34
  • As denoted on the docs: restrict sum to numbers :-) you will have less headaches. Make a few explicit constructs if you have to concatenate nested lists - you will have more maintainable code anyway. Commented Aug 30, 2012 at 17:39

4 Answers 4

21

Sum does something like this

def sum(values, start = 0):
    total = start
    for value in values:
        total = total + value
    return total

sum([1,2],[3,4]) expands something like [3,4] + 1 + 2, which you can see tries to add numbers and lists together.

In order to use sum to produce lists, the values should be a list of lists, whereas start can be just a list. You'll see in your failing examples that the list contains at least some ints, rather then all lists.

The usual case where you might think of using sum with lists is to convert a list of lists into a list

sum([[1,2],[3,4]], []) == [1,2,3,4]

But really you shouldn't do that, as it'll be slow.

Sign up to request clarification or add additional context in comments.

2 Comments

more like total = total + value which is why sum has quadratic performance for lists
@gnibbler, that's true. I hadn't thought about that.
5
a=[[1, 20], [2, 3]]
b=[[[[[[1], 2], 3], 4], 5], 6]
sum(b, a)

This error has nothing to do with the start parameter. There are two items in the list b. One of them is [[[[[1], 2], 3], 4], 5], the other is 6, and a list and int cannot be added together.

sum(a, b)

This is adding:

[[[[[[1], 2], 3], 4], 5], 6] + [1, 20] + [2, 3]

Which works fine (as you're just adding lists to lists).

a=[1,2]
b=[3,4]
sum(a,b)

This is trying to add [3,4] + 1 + 2, which again isn't possible. Similarly, sum(b,a) is adding [1, 2] + 3 + 4.

What if the start is not a string and not an integer?

sum can't sum strings. See:

>>> sum(["a", "b"], "c")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: sum() can't sum strings [use ''.join(seq) instead]

Comments

4

One of the things that has been hinted at but not explicitly stated in the other answers is that the start value defines the type for the return value and for the items being summed. Because the default is start=0, (and 0 is an integer, of course) all items in the iterable must be integers (or types with an __add__ method that works with integers). Other examples have mentioned concatenating lists:

(sum([[1,2],[3,4]], []) == [1,2,3,4])

or timedate.timedelta objects:

(sum([timedelta(1), timedelta(2)], timedelta()) == timedelta(3)).

Notice that both examples pass an empty object of the type in the iterable as the start parameter to avoid getting a TypeError: unsupported operand type(s) for +: 'int' and 'list' error.

Comments

0

I just wanted to clarify some confusion.
The signature of sum function should be:

sum(iterable,start=0) 

rather than

sum(values,start=0)

as written above. This change will make the signature clearer.

Full function:

def sum(iterable,start=0):
       total=start
       for val in iterable:
            total+=val
       return total

2 Comments

This seems to be a comment/edit suggestion rather than a separate answer. Note that the sum builtin takes no keyword arguments; the names of the parameters are inconsequential.
Actually i was trying to explain how the built -in sum function works in practice.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.