[Python-Dev] Fwd: summing a bunch of numbers (or "whatevers")

Guido van Rossum guido@python.org
Mon, 21 Apr 2003 09:43:09 -0400


> Just to make sure I understand the desired semantics, is this Python
> implementation of sum() accurate:

We're no longer aiming for this, but let me point out the fatal flaw
in this approach:

> def sum(l):
>     '''sum(sequence) -> value
> 
>        Returns the sum of a non-empty sequence of numbers (or other objects
>        that can be added to each other, such as strings, lists, tuples...).'''
> 
>     it   = iter(l)
>     next = it.next
> 
>     try:
>         first = next()
>     except StopIteration:
>         raise ValueError, 'sum() arg is an empty sequence'
> 
>     # Special-case sequences of strings, for speed 
>     if isinstance(first, str):
>         try:
>             return first + ''.join(it)
>         except:
>             pass

Suppose the iterator was iter(["a", "b", "c", 1, 2, 3]).  The "a" is
held in the variable 'first'.  The "".join() code consumes "b", "c"
and 1, and then raises an exception.  At this point, there's no way to
recover the values swallowed by "".join(), so there's no way to
continue.  But letting the exception raised by "".join() propagate
isn't right either: suppose that instead of [1, 2, 3] the sequence
ended with some instances of a class that knows how to add itself to a
string: the optimization attempt would cause an error to be thrown
that wouldn't have been thrown without the optimization, a big no-no
for optimizations.

>     try:
>         while 1:
>             first += next()
> 
>     except StopIteration:
>         return first
> 
> The speed optimization for string sequences is slightly different, but
> exposes the same fast-path for the vast majority of likely inputs.

Of course, it might have been okay to only invoke "".join() if the
argument was a *list* of strings.

--Guido van Rossum (home page: http://www.python.org/~guido/)