Emile van Sebille said:
On 5/1/2009 7:31 AM J Kenneth King said...
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.
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...
... if len(j)==2:
... for item in j:
... if item % 2:
... b.append(item)
...
Much nicer. Thank you.