Convenient filtering in for cycles

  • Thread starter Stefano Maggiolo
  • Start date
S

Stefano Maggiolo

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)
======

Let's say that my dream syntax would be

===(2)===
for x in l if P(x):
do_stuff(x)
======

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)
======

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

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

As I see it, every syntax-valid solution has its drawbacks:
(1) adds an indentation level;
(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);
(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?

Pardon my boldness, but I am asking this because there are two invalid
construct that I keep writing when I don't pay attention: one is (2),
and the other is list comprehensions as in

===(6)===
for x in (x in l if P(x)):
do_stuff(x)
======

which accidentally would be a better solution than (1), (3), (4), (5),
though not as good as (2).

Thank you for your attention,
Stefano Maggiolo
 
S

Steven D'Aprano

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?
 
A

alex23

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)
======

map(do_stuff, filter(P, l))
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,774
Messages
2,569,598
Members
45,152
Latest member
LorettaGur
Top