425,979 Members | 951 Online
Need help? Post your question and get tips & solutions from a community of 425,979 IT Pros & Developers. It's quick & easy.

# When is List Comprehension inappropriate?

 P: n/a 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. Thanks, Ben Mar 19 '07 #1
14 Replies

 P: n/a Ben

 P: n/a On Mar 19, 9:41 am, "Ben"

 P: n/a On 19 Mar 2007 07:41:59 -0700, Ben

 P: n/a "Ben" Feel free to tell me a different way to do this, as well. Untested code, but I would try to avoid calling getpixel: data = list(im.getdata()) width, height = im.size even = [ data[i:i+width:2] for i in range(0, width*height, 2*width)] That creates a 2 dimensional list rather than one long list, and doesn't create the x,y tuples, but since they are implied by the position in the list I don't actually see why you would want to create them at all. You can calculate them separately if you actually need them. Mar 19 '07 #5

 P: n/a On Mon, 19 Mar 2007 07:41:59 -0700, Ben 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. Others have suggested reasons why you might or might not want to use list comprehensions. Here's three more reasons: * You have a LOT of data to handle. (But remember that a lot to you might not be a lot to your computer.) * You don't need to handle the items all at once, and can handle the items one at a time instead. Use an iterator, generator expression, or other lazily-evaluated function instead. That way you avoid forming the list all at once. * You have to write code that's backwards-compatible to an old version of Python. Use a list and a for-loop. -- Steven. Mar 20 '07 #6

 P: n/a BJörn Lindqvist

 P: n/a BJörn Lindqvist: While they may be faster, Psyco is great here. Also, if you have lots of 2d-loops like "for x in something: for y in something:", then it could be more beautiful to separate the iteration from the task: def iterimage(im, width, height, step = 1): for y in range(0, height, step): for x in range(0, width, step): yield (x, y), im.getpixel((x, y)) Just a note: Psyco usually isn't able to speed up generators (ShedSkin recently has hadded a support of them too, and it seem fast enough). Bye, bearophile Mar 20 '07 #8

 P: n/a Alex Martelli wrote: BJörn Lindqvist even2 = [(pos, col) for pos, col in iterimage(im, width, height, 2)] list(iterimage(etc etc)) is surely a better way to express identical semantics. More generally, [x for x in whatever] (whether x is a single name or gets peculiarly unpacked and repacked like here) is a good example of inappropriate LC, to get back to the question in the subject: list(whatever) is the "one obvious way" to perform the same task. Clearly the comprehension you complain about is sub-optimal. The essential difference, however, is between [x for x in iterimage(im, width, height, 2)] and list(iterimage(im, width, height, 2)) I agree that the latter is the obvious way, but the difference isn't as large as your leap makes it look - and we had to await the invention of the generator expression for it to be a practical choice. regards Steve -- Steve Holden +44 150 684 7255 +1 800 494 3119 Holden Web LLC/Ltd http://www.holdenweb.com Skype: holdenweb http://del.icio.us/steve.holden Recent Ramblings http://holdenweb.blogspot.com Mar 20 '07 #9

 P: n/a In article <1h***************************@mac.com>, Alex Martelli list(iterimage(etc etc))is surely a better way to express identical semantics. More generally,[x for x in whatever] (whether x is a single name or gets peculiarlyunpacked and repacked like here) is a good example of inappropriate LC,to get back to the question in the subject: list(whatever) is the "oneobvious way" to perform the same task. Except of course, when it's [x for x in whatever if x] I'm exceedingly fond of replacing filter() with listcomps. They're so much more readable and often faster. -- Aahz (aa**@pythoncraft.com) <* http://www.pythoncraft.com/ "Typing is cheap. Thinking is expensive." --Roy Smith Mar 20 '07 #10

 P: n/a Aahz , Alex Martelli

 P: n/a On Mar 19, 2:41 pm, "Ben" ># some random rangesdata = [range(random.randrange(3,7)) for x in range(4)]# but I want each range jumbled[ random.shuffle(d) for d in data] [None, None, None, None] >>data [[2, 0, 3, 1], [0, 2, 1], [3, 4, 1, 0, 2], [2, 1, 0, 3]] >>> (I do know how to re-write it). - Paddy. Mar 21 '07 #12

 P: n/a Steve Holden

 P: n/a Paddy # some random rangesdata = [range(random.randrange(3,7)) for x in range(4)]# but I want each range jumbled[ random.shuffle(d) for d in data] [None, None, None, None] >data [[2, 0, 3, 1], [0, 2, 1], [3, 4, 1, 0, 2], [2, 1, 0, 3]] >> (I do know how to re-write it). for d in data: random.shuffle(d) Alex Mar 22 '07 #14

 P: n/a On Mar 22, 4:56 am, a...@mac.com (Alex Martelli) wrote: Paddy ># some random ranges >>data = [range(random.randrange(3,7)) for x in range(4)] >># but I want each range jumbled >>[ random.shuffle(d) for d in data] [None, None, None, None] >>data [[2, 0, 3, 1], [0, 2, 1], [3, 4, 1, 0, 2], [2, 1, 0, 3]] (I do know how to re-write it). for d in data: random.shuffle(d) Alex Hah, "You just couldn't let it lie" ;-) I just knew someone would bite, and re-write it. Now to reel, you in. Its fish for dinner today! - Paddy. Mar 22 '07 #15

### This discussion thread is closed

Replies have been disabled for this discussion.