[Python-ideas] Fast sum() for non-numbers

Steven D'Aprano steve at pearwood.info
Fri Jul 5 06:06:23 CEST 2013


On 04/07/13 19:54, Sergey wrote:
> On Jul 04, 2013 Steven D'Aprano wrote:
>
> This message is long, so here's its short summary:
> * Unfortunately list.extend does not look like the obvious way, and
>    its slower than alternatives.

[snip]


I'm not going to get into a long and tedious point-by-point argument about this, but I will just re-iterate:

I don't accept that using sum on non-numbers ought to be encouraged, although I don't think it should be prohibited either. So I'm at best neutral on speeding up sum for lists. However, some things do need to be said:

1) Alex Martelli is, or at least was, against using sum on non-numbers:

[quote]
I was responsible for designing sum and doing its first implementation in the Python runtime, and I still wish I had found a way to effectively restrict it to summing numbers (what it's really good at) and block the "attractive nuisance" it offers to people who want to "sum" lists;-). – Alex Martelli Jun 4 '09 at 21:07
[end quote]

This quote is from the Stackoverflow question you linked to earlier:

http://stackoverflow.com/questions/952914/making-a-flat-list-out-of-list-of-lists-in-python


2) You should not be benchmarking against 2.7, but 3.3. On my machine, using 3.3, list.extend is just as fast as using itertools, and both are faster than a list comprehension. (I have not tested your patched version of sum.) Augmented assignment is faster, but faster still is an optimized version using extend that avoids a name look-up:

The tests I ran:

python3.3 -mtimeit --setup="x=[[1,2,3]]*100000" "[i for l in x for i in l]"

python3.3 -mtimeit --setup="x=[[1,2,3]]*100000" \
   --setup="from itertools import chain" \
   "list(chain.from_iterable(x))"

python3.3 -mtimeit --setup="x=[[1,2,3]]*100000" \
     --setup="from itertools import chain" \
     "list(chain(*x))"

python3.3 -mtimeit --setup="x=[[1,2,3]]*100000" --setup="l = []" \
     "for i in x: l += i"

python3.3 -mtimeit --setup="x=[[1,2,3]]*100000" --setup="l = []" \
     "for i in x: l.extend(i)"

python3.3 -mtimeit --setup="x=[[1,2,3]]*100000" --setup="l = []" \
     --setup="extend=l.extend" \
     "for i in x: extend(i)"


with results, from slowest to fastest:

list comp: 32.8 msec per loop
chain: 21 msec per loop
extend: 20.4 msec per loop
chain_from_iterable: 19.8 msec per loop
augmented assignment: 12.8 msec per loop
optimized extend: 11.7 msec per loop


On your machine, results may differ.


-- 
Steven


More information about the Python-ideas mailing list