[Python-ideas] if-statement in for-loop

Paul Moore p.f.moore at gmail.com
Sun Sep 11 07:59:50 EDT 2016


On 11 September 2016 at 10:36, Dominik Gresch <greschd at gmx.ch> wrote:
> I've recently found myself writing code similar to this:
>
> for i in range(10):
>     if i == 5:
>         continue
>     "body"
>
> which I find a bit ugly.

I write code like this quite frequently. However, unlike you I don't
find it particularly ugly. It's essentially the primary purpose of the
"continue" statement.

[...]

> So I asked myself if a syntax as follows would be possible:
>
> for i in range(10) if i != 5:
>     body
>
> Personally, I find this extremely intuitive since this kind of if-statement
> is already present in list comprehensions.

I find it less readable than the version using "continue". Maybe
that's because the inverted condition doesn't match how I think of
this - "go through all the integers but skip 5" rather than "go
through all the integers which aren't 5". It's certainly subjective,
though, and there's no objective reason for comparing one over the
other.

> What is your opinion on this? Sorry if this has been discussed before -- I
> didn't find anything in the archives.

My feeling is that it doesn't add enough to warrant dedicated syntax.
The quest to compress everything into a single line doesn't feel in
the spirit of Python to me - it reminds me of Perl, with its plethora
of if, when and unless statements and statement modifiers. And
personally, I tend to use "does it feel like Perl" as a test for "is
it inappropriate for Python".

If the logic for what to skip and what to keep was complicated, I'd
probably end up writing a custom generator - so this proposed syntax
would likely only be needed for simple cases, and in such cases, it
doesn't seem worth it just to avoid a one or two line "continue".

Looking at alternative formulations which we can use withing Python as
it now stands, I can think of:

# Your original
for i in range(10):
    if i == 5:
        continue
    body()

# Compressed in case you don't like the 2-line continue
for i in range(10):
    if i == 5: continue
    body()

# Hacky use of a generator expression:
for i in (x for x in range(10) if x != 5):
    body()

# Custom generator - looks a bit silly for something this simple
# but quite reasonable for many "real life" examples
def gen():
    for i in range(10):
        if i != 5
            yield i

for i in gen():
    body()

# Functional style
for i in filter(range(10), lambda n: n != 5):
    body()

There's a lot of opportunity here for picking a style that you're
comfortable with. So it's hard to see this issue as being worth
additional syntax. And conversely, if we did have the proposed syntax,
I suspect there would be a tendency for certain types of developer to
try to cram far too much logic into the "if" clause, when one of the
above approaches would be more readable. Of course, you can write bad
code with or without extra syntax, but it just feels to me like we'd
end up with the proposed syntax being used more often in cases where
it damages readability, than in cases where it's appropriate.

That's not to say that there may not be a good justification for the
proposal - just that your example isn't compelling to me.

Paul


More information about the Python-ideas mailing list