[Python-Dev] Rationale for sum()'s design?

Nick Coghlan ncoghlan at iinet.net.au
Mon Mar 14 15:05:32 CET 2005

```Alex Martelli wrote:
>
> On Mar 14, 2005, at 11:20, Nick Coghlan wrote:
>    ...
>
>> Somewhat ugly, but backwards compatible:
>
>
> I realize you're mostly talking semantics, not implementation, but, as
> long as we're at it, could we pretty please have back the optimization
> indicated by...:

It turns out the sentinel value isn't really needed either:

def sum(*args):
itr = iter(args[0])
try:
value = args[1]
except IndexError:
# No start value, so use the type of the first element
try:
first = itr.next()
except StopIteration:
# Empty iterable, return 0 for backwards compatibility
# When summing over something other than a sequence of
# numbers, giving an initial value is a good idea.
return 0
# Use default constructor to get initial value
value = type(first)()
value += first
# Special case optimisation of strings
if isinstance(value, basestring):
# Rely on ''.join promoting to unicode if needed
return value + ''.join(itr)
for item in itr:
value += item
return value

I'm not sure how much we really gain though - at the moment, using sum() for
anything other than numbers gives an immediate exception. With the behaviour
above, it appears to work, but will return 0 for an empty sequence instead of
the additive identity of the desired type (e.g. "" or []). So the error will
turn up somewhere else, instead of as an explicit exception at the point of origin.

Maybe what we really should be doing is trapping the TypeError, and generating a
more meaningful error message.

E.g.

Py> def sum(seq, initial=0):
...   itr = iter(seq)
...   try:
...     first = itr.next()
...   except StopIteration:
...     return 0
...   value = initial
...   try:
...     value += first
...   except TypeError:
...     raise TypeError("Cannot add first element %r to initial value %r" % (fir
st, value))
...   for item in itr:
...     value += item
...   return value
...
Py> seq = ([1], [2], [3])
Py> sum(seq)
Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "<stdin>", line 11, in sum
TypeError: Cannot add first element [1] to initial value 0
Py> sum(seq, [])
[1, 2, 3]
Py> seq = ('1', '2', '3')
Py> sum(seq)
Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "<stdin>", line 11, in sum
TypeError: Cannot add first element '1' to initial value 0
Py> sum(seq, '')
'123'

--
Nick Coghlan   |   ncoghlan at email.com   |   Brisbane, Australia
---------------------------------------------------------------
http://boredomandlaziness.skystorm.net
```