[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)
   # Add the elements
   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


More information about the Python-Dev mailing list