[Python-ideas] With clauses for generator expressions

Andrew Barnert abarnert at yahoo.com
Thu Nov 15 12:11:07 CET 2012

> From: Phil Connell <pconnell at gmail.com>
> Sent: Thu, November 15, 2012 1:24:52 AM
> On Wed, Nov 14, 2012 at 07:44:44PM -0800, Andrew Barnert wrote:
> > 
> >     upperlines =  (lines.upper() for line in file with open('foo', 'r') as 
> While this  looks very clean, how do you propose the following should be 
> as a  generator expression?
> def foo():
>     with open('foo') as  f:
>         for line in f:
>              if 'bar' in line:
>                  yield line

Exactly as you suggest (quoting you out of order to make the answer clearer):

> (line
> for line in f
> if bar in 'line'
> with open('foo') as f)

> An obvious suggestion is as follows, but I'm  not totally convinced about the
> out-of-order with, for and if clauses  (compared with the equivalent 

The clauses have *always* been out of order. In the function, the "if" comes 
between the "for" and the yield expression. In the expression, the "for" comes 
in between. If the clause order implies the statement order (I would have put it 
in terms of the clause structure implying the scoping, but they're effectively 
the same idea), then our syntax has been wrong since list comprehensions were 
added in 2.0. So, I think (and hope!) that implication was never intended.

Which means the only question is, which one looks more readable:

1. (foo(line) for line in baz(f) if 'bar' in line with open('foo') as f)
2. (foo(line) for line in baz(f) with open('foo') as f if 'bar' in line)
3. (foo(line) with open('foo') as f for line in baz(f) if 'bar' in line)

Or, in the trivial case (where versions 1 and 2 are indistinguishable):

1. (line for line in f with open('foo') as f)
2. (line for line in f with open('foo') as f)
3. (line with open('foo') as f for line in f)

My own intuition is that 1 is the clearest, and 3 by far the worst. So, that's 
why I proposed order 1. But I'm not at all married to it.

More information about the Python-ideas mailing list