Convenient filtering in for cycles

Steven D'Aprano steve+comp.lang.python at pearwood.info
Wed Oct 5 22:08:46 EDT 2011


On Wed, 05 Oct 2011 18:55:53 +0200, Stefano Maggiolo wrote:

> Dear all,
> 
> I would like to know if there is a (more) convenient way of doing this
> structure:
> 
> ===(1)===
> for x in l:
>     if P(x):
>         do_stuff(x)
> ======

That seems pretty convenient to me. It's simple, obvious and readable.


 
> Let's say that my dream syntax would be
> 
> ===(2)===
> for x in l if P(x):
>     do_stuff(x)
> ======

That is exactly the same as #1 above, except it takes one extra line 
(trivial) and one extra indent level (almost always trivial). So what's 
the problem with #1?

If you have so many indent levels that one more level causes you grief, 
then consider that Nature's way of telling you that you have too much 
code in one chunk and that you should refactor some of it into functions.



> as if it was the second part of a list comprehension. But sadly it is
> not in the language. Obvious alternatives are
> 
> ===(3)===
> for x in (x for x in l if P(x)):
>     do_stuff(x)
> ======

A hard to read mess. Best avoided.



> ===(4)===
> for x in l:
>     if not P(x):
>         continue
>     do_stuff(x)
> ======

Saves an indent level, otherwise virtually identical to #1.


 
> ===(5)===
> [do_stuff(x) for x in l if P(x)]
> ======

Only appropriate if you care about the return results of do_stuff. If you 
are using a list comprehension solely for the side-effects, don't.



> As I see it, every syntax-valid solution has its drawbacks: (1) adds an
> indentation level;

This shouldn't be a drawback. This should be an advantage. It's an extra 
indentation level because it represents a block of code.


> (3) adds an unnatural repetition of variable names and "for"; (4) has
> the "masked goto" continue (even if it is quite easy to understand what
> happens);

While it is true that "goto is harmful", it is possible to take the 
hatred of goto to ridiculous levels. 

Calling a function is a "masked goto". For-loops and while loops are 
"masked gotos". That doesn't make them bad things.

There is nothing inherently wrong with continue and break for flow 
control, although of course you can write bad code with any construct.


> (5) is good but not usable when do_stuff is what it usually is, that is
> a list of instructions.
> 
> Is there some better and valid construction I missed? If not, is there a
> reason why (2) is not in the language?

Because it complicates the language for very little benefit. That makes 
the language harder to learn and read and the compiler harder to 
maintain. Unless there is a concrete gain from the feature, why bother?



-- 
Steven



More information about the Python-list mailing list