[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
>file)
>
> While this looks very clean, how do you propose the following should be
>written
> 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
generator)
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