When is List Comprehension inappropriate?
Alex Martelli
aleax at mac.com
Mon Mar 19 11:01:59 EDT 2007
Ben <bensherman at gmail.com> wrote:
> I have recently learned how list comprehension works and am finding it
> extremely cool. I am worried, however, that I may be stuffing it into
> places that it does not belong.
>
> What's the most "pythony" way to do this:
>
> even = []
> for x in range(0,width,2):
> for y in range(0,height,2):
> color = im.getpixel((x,y))
> even.append(((x,y), color))
>
> versus list comprehension:
>
> even2 = [((x,y), im.getpixel((x,y))) for x in range(0,width,2) for y
> in range(0,height,2)]
>
> Is there a computational difference in creating a blank list and
> appending to it versus doing a list comprehension? Are there
> advantages to it outside of short and pretty code?
>
> Feel free to tell me a different way to do this, as well.
I like list comprehensions when I'm building up a list, originally
empty, with .append calls within for loops (possibly with an if guard),
unless I need (e.g.) a conditional break, which LCs don't support.
IOW, I would use a LC in your example. However, I would format it more
neatly:
even2 = [((x,y), im.getpixel((x,y)))
for x in range(0,width,2)
for y in range(0,height,2)]
though I guess that's a matter of taste.
Some people think that LCs should not be used except for extremely
simple cases, but I personally disagree with that stance.
The cases where an LC should NOT be used are those in which you are not
really building a list as above described, but e.g. "just looping".
To check whether LC is faster than, slower than, or equal to a more
extensive loop, use timeit, e.g.:
brain:~/py25/Doc alex$ python -mtimeit -s'xs=range(83)' 'L=[]' 'for x in
xs: L.append(x*x)'
10000 loops, best of 3: 34.6 usec per loop
brain:~/py25/Doc alex$ python -mtimeit -s'xs=range(83)' 'L=[x*x for x in
xs]'
100000 loops, best of 3: 19.4 usec per loop
So for this simple case, it may look like the LC is much faster;
however:
brain:~/py25/Doc alex$ python -mtimeit -s'xs=range(83)'
'L=[];ap=L.append' 'for x in xs: ap(x*x)'
10000 loops, best of 3: 22.3 usec per loop
...as you can see, hoisting the L.append lookup out of the loop accounts
for most of the difference.
Alex
More information about the Python-list
mailing list