[Python-ideas] With clauses for generator expressions

Andrew Barnert abarnert at yahoo.com
Thu Nov 15 15:25:57 CET 2012

From: Serhiy Storchaka <storchaka at gmail.com>
Sent: Thu, November 15, 2012 4:17:42 AM

> On 15.11.12 13:11, Andrew Barnert wrote:
> > 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)
> What about such  generator?
> def gen():
>     with a() as f:
>          for x in f:
>             if  p(x):
>                 with b(x) as  g:
>                     for  y in g:
>                          if q(y):
>                              yield  y

Mechanically transforming that is easy. You just insert each with along with its 
corresponding for and if. There are no ambiguities for any of the three 
potential rules:

1. (y for x in f if p(x) with a() as f for y in g if q(y) with b(x) as g)
2. (y for x in f with a() as f if p(x) for y in g with b(x) as g if q(y))
3. (y with a() as f for x in f if p(x) with b(x) as g for y in g if q(y))

I suppose you could also argue for a "super-1" where we stick all the withs at 
the end, or a "super-3" where we stick them all at the beginning… but it's hard 
to see a compelling argument for that. In fact, despite everything I said about 
clause structure not implying nesting, either one of those would look to me as 
if all the withs were at the outermost scope.

At any rate, unlike the simpler cases, here I have no opinion on which of those 
is clearest. They're all impossible to read at a glance (although breaking them 
up into multiple lines helps, I still don't have any clue what even the original 
function means—all those one-letter variables and functions, with 
easily-confused letters to boot…). But they're all quite easy to work out, or to 
construct, if you understand nested generator expressions and know the rule for 
where each clause goes.

More information about the Python-ideas mailing list