On Tue, 2009-05-05 at 12:15 -0400, J Kenneth King wrote: > Emile van Sebille <em...@fenx.com> writes: > > > On 5/1/2009 7:31 AM J Kenneth King said... > >> Chris Rebert <c...@rebertia.com> writes: > >>> b = [] > >>> for pair in a: > >>> for item in pair: > >>> b.append(item) > >> > >> This is much more clear than a nested comprehension. > >> > >> I love comprehensions, but abusing them can lead to really dense and > >> difficult to read code. > > > > I disagree on dense and difficult, although I'll leave open the > > question of abuse. > > Dense and difficult may be subjective to people like you or I, but you > left out the "to read" part of that sentence. I was referring to the > negative effect nested or complex list comprehensions can have on > readability. > > > b = [ item for pair in a for item in pair ] > > It's a clever statement, but use it once and its gone. Why not use the > expanded form in a function definition and get an even shorter, but > clearer statement? >
It's also not obvious what it means. I would have thought the proper incantation would be: [item for item in pair for pair in a] but that returns [5,5,5,6,6,6]. I still haven't figured out why. The way you have to bounce your eyes back and forth in the comprehension makes it hard to read the logic. With the loop, on the other hand it is blatantly obvious which way the nesting occurs. > > >>> b = flatten(a) > > Boom, done. > > > This is exactly the code above expressed in comprehension form. > > > > It's worth knowing that a list comprehension is structured identically > > to the equivalent for loop. So it really is neither more dense nor > > more difficult to read. Further, you can tell immediately from the > > start of the list comprehension what you've got -- in this case a list > > of item(s). Empirically, I'd have to disagree with you. The structure is changed by the fact that "item" gets put at the beginning of the comprehension. With the loop, each variable gets introduced in a for statement, and then used. With the list comprehension, "item" gets used at the beginning, and then assigned to in the for expression at the end. Meanwhile, pair gets introduced as the loop variable in the first for expression, and iterated over in the second for expression. So do you read it left to right or right to left? Neither. You have to hold the whole expression in your mind at once. Good for short and simple comprehensions, bad as they get more complicated. > > > > Here with some slight changes... > > > >>>> a = [(1, 2), (3, 4, 7), (5, 6)] > >>>> [ item for j in a if len(j)==2 for item in j if item % 2 ] > > [1, 5] > > This, to me, looks like line noise, approaching perl in its unreadability. > > ...opposed to... > > > >>>> for j in a: > > ... if len(j)==2: > > ... for item in j: > > ... if item % 2: > > ... b.append(item) > > ... > >>>> b > > [1, 5] > >>>> > Much nicer. Thank you. > Thanks for the lesson in list comprehensions, but I'm well aware of > how they work. > > List comprehensions can make a reader of your code apprehensive > because it can read like a run-on sentence and thus be difficult to > parse. The Python documentation discourages their use and I believe > for good reason. It's much easier to explain complex processes with a > function rather than a single nested statement. > > > > > YMMV, > > > > Emile > > It will apparently vary greatly. Depending on how much coffee I've > had. > > ;) > > J > -- > http://mail.python.org/mailman/listinfo/python-list > -- http://mail.python.org/mailman/listinfo/python-list