[Tutor] Using a list comp in place of a for loop

Rich Lovely roadierich at googlemail.com
Mon Oct 5 00:17:53 CEST 2009


2009/10/3 afith13 <afith13 at gmail.com>:
> Hi tutors,
>
> I've got a loop and a comprehension that do the same thing (as far as I can tell):
>
> for i in range(N):
>  someList.append.newObject(i)
>
> ...and...
>
> [someList.append.newObject(i) for i in range(N)]
>
> I'm tempted to write this as a list comp because it's a big list and I've read that list comps are faster than for loops in general. I'm hesitating because I'm not sure if building a big list of "None" objects and then throwing it away has any drawbacks.
>
> Thanks in advance,
> _______________________________________________
> Tutor maillist  -  Tutor at python.org
> To unsubscribe or change subscription options:
> http://mail.python.org/mailman/listinfo/tutor
>

If you want a list comprehension to do the same as your original code,
you need to write it as

someList = [newObject(i) for i in range(N)]

This avoids building the list of Nones, and only differs if someList
already has values in it, in which case you can use:

someList.extend(newObject(i) for i in range(N))

which will do exactly what your original code does, except using a
list comp (actually a generator, which is pretty much the same thing),
and won't generate and then throw away a list of Nones.

I prefer list comprehensions over for-loops wherever possible because
they're easier to read (IMHO).  As for speed, let's take a look:

>>> t_for = Timer("""l = []
... for i in range(100):
...     l.append(i)""")
>>> t_slowComp = Timer("""l = []
... [l.append(i) for i in range(100)]
... """)
>>> t_comp = Timer("""l = [i for i in range(100)""")
>>> t_addComp = Timer("""l = []
... l += [i for i in range(100)]""")
>>> t_extend = Timer("""l = []
... l.extend(i for i in range(100))""")
>>> min(t_for.repeat(3,10000))
0.8266444478279027
>>> min(t_slowComp.repeat(3,10000))
0.95501802603394026
>>> min(t_comp.repeat(3,10000))
0.35897579161587601
>>> min(t_addComp.repeat(3,10000))
0.37727895584498583
>>> min(t_extend.repeat(3,10000))
0.59708203137552118
>>>

As you can see, list comprehensions are better than twice the speed
(in this simple example) of a regular for loop.  With an existing
list, adding a comprehension is surprisingly fast (I was expecting
extend to be faster).  I wasn't expecting the slow comprehension to be
as slow as it is, but as you can see, it is slower than a standard for
loop.


Hope something in here has helped you, and has answered your question(s).
-- 
Rich "Roadie Rich" Lovely

There are 10 types of people in the world: those who know binary,
those who do not, and those who are off by one.


P.S. In case you're wondering, I feel the minimum of Timer.repeat()
results is more applicable than an average, as I feel - and the docs
agree - that it's a sort of "best speed", ignoring as many other
drains of processing power as possible.)


More information about the Tutor mailing list