list comprehension question

J. Cliff Dyer jcd at sdf.lonestar.org
Tue May 5 14:01:02 EDT 2009


On Tue, 2009-05-05 at 12:15 -0400, J Kenneth King wrote:
> Emile van Sebille <emile at fenx.com> writes:
> 
> > On 5/1/2009 7:31 AM J Kenneth King said...
> >> Chris Rebert <clp2 at 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
> 




More information about the Python-list mailing list