Pythonic way to sum n-th list element?

Alex Martelli aleax at aleax.it
Mon Apr 21 18:02:27 CEST 2003


Steve Holden wrote:
   ...
>> Interesting... I have my doubts on whether Guido would
>> accept such a patch just a week before a beta, but maybe
>> I should try submitting it anyway...
> 
> Only one way to resolve those doubts.

Yup -- proof of the pudding, and all that.  So, I submitted it and
Guido accepted it for 2.3, EXCEPT...:

> The use of sum() to concatenate a list (please, not a tuple!) of strings
> in such a deterministic way is a masterstroke. It would surely deserve to
> become immediately idiomatic.

...that sum(manystrings) was rejected -- now, when called with any
sequence of strings, sum will raise a TypeError, and remind the user
to use ''.join instead.  Not sure why you wanted sum to differentiate
between its argument being a list or tuple when all similar built-ins 
these days accept any iterable, but anyway the problem that led to
this came when the argument is an *iterator* -- sum had to jump through
weird hoops to guarantee correct behavior on an iterator (particularly
one freely mixing unicode and non-unicode strings), leading to a factor
of two slowdown with respect to ''.join, and still couldn't ensure the
same semantics as a loop with += in sufficiently weird cases such as:

class Gotcha:
    def __add__(self, *whatever): return 23

weirdlist = [ 'xx', Gotcha() ]
print sum(weirdlist)


This _should_ have printed 23, just like reduce(operator.add,weirdlist)
does -- however, due to the string special-case, it ended up delegating
to ''join and thereby raising a TypeError instead.  All in all, it did
make much more sense to forbid the first item from being a string (so
as to avoid the performance trap of strings-concatenation done by +).

Interestingly, and characteristically, Tim Peters had expressed strong
instinctive dislike to sum being applicable to (and indeed special-case
optimized for) sequences of strings, even before we had unearthed these
weird examples making the prohibition well-nigh inevitable.  timbot
argued that "sum is about numbers" -- and soon he was proved right.


As a bonus -- sum([]) now returns 0, while in my original design it
raised a ValueError, just like e.g. max([]) does.  I thought raising an
error was best in the name of "errors shouldn't pass silently" and "in
the face of ambiguity, refuse the temptation to guess".  But -- once
we decree that "sum is about numbers", there's no real ambiguity, so we
can have the little extra handiness of having sum([]) not be an error;-).


Alex





More information about the Python-list mailing list