Proposal: [... for ... while cond(x)]

Nick Mellor thebalancepro at gmail.com
Thu Sep 26 10:39:30 EDT 2013


Hi all,

It might be a risk that we create some hairy or subtle semantics, but perhaps this idea has legs. The 'pythonic' syntax is very attractive.

# skip the silence at the start
data = (amp for amp in signal from abs(amp) > 0.05)

# drop files that are less than 600 bytes
# (already sorted into ascending order of size)
files = (file for file in filelist from os.stat(file).st_size > 600)

# Analyse bunch of log lines up to a certain timestamp
cutoff = datetime.datetime.now() - datetime.timedelta(hours=1)
checklogs = (entry for entry in log while entry.timestamp <= cutoff)

In use it feels along the same lines as else: clauses in try/finally and for loops, both of which I like-- it seems natural in Python, keeps the meaning clear and consistent, avoids complicated, iterative, inexpressive code.

Terry Reedy wrote:
> You're right. The syntax is ambiguous. I agree it's not a good idea,
now. :)

When while, if and from are made mutually exclusive, not mixed, on a comprehension clause, it looks to me like the ambiguity disappears:

> x for x in xs while cond(x) if blah(x)

not legal Python-- if and while are mutually exclusive on the same comprehension clause. On the one hand it's like writing x for x in xs if f(x) < 10 if g(x) > 100, the illegality of which no-one is complaining about. Just write:

x for x in xs while cond(x) and cond2(x)

or

x for x in xs if cond(x) and cond2(x)

If there is a need to filter using if as well as while, then use two comprehensions:

intermediate = [x for x in xs while cond(x)]
final = [x for x in intermediate if cond2(x)]

or the same comprehension applied to itself:

y for y in x for x in xs if cond(x) while cond2(y)

The if and the while operation *should* be kept separate-- they're different stages of processing the data.

> > x*y for x in xs while cond(x) for y in ys if cond(y)

legal Python-- the 'if cond(y)' unambiguously refers to the inner comprehension. 


> x for x in xs if blah(x) while cond(x)

not legal Python-- if and while are mutually exclusive in the same comprehension clause.

The objection to "while" as an abbreviation:

> e(x) for x in xs if cond(x)
> 
> is an abbreviation of
> 
> for x in xs:
>   if cond(x)
>     yield e(x)
> 
> and similarly with more for and if clauses,
> whereas the analogous expansion of your proposal
> 
> for x in xs:
>   while cond(x):
>      yield e(x)
> 
> is an infinite loop and not at all what you mean.

That's because while is being used here with a different semantic to the while loop. It actually means:

for x in xs:
    if not cond(x):
        break
    yield e(x)

and for 'from':


emit = False
for x in xs:
    if not emit:
        if cond(x):
            emit = True
    else:
        yield e(x)


Cheers,

Nick



More information about the Python-list mailing list