[Python-ideas] if-syntax for regular for-loops

2 views
Skip to first unread message

Andreas Nilsson

unread,
Oct 3, 2008, 7:17:53 AM10/3/08
to python...@python.org
Hi.
I'm reposting this here after erroneously posting it on python-dev.

I use list comprehensions and generator expressions a lot and lately
I've found myself writing a lot of code like this:

for i in items if i.some_field == some_value: i.do_something()

Naturally it won't work but it seems like a pretty straight-forward
extension to allow compressing simple loops to fit on one line. The
alternative, in my eyes, suggests there's something more happening
than a simple include-test which makes it harder to comprehend.

for i in items:
if i.some_field == some_value: i.do_something()

One possibility of course is to use a generator-expression but that
makes it look like there are two for loops and it feels like a waste
setting up a generator just for filtering.

for i in (i for i in items if some_field == some_value):
i.do_something()

Stupid idea? Am I missing some obviously better way of achieving the
same result?

Thanks,
Adde
_______________________________________________
Python-ideas mailing list
Python...@python.org
http://mail.python.org/mailman/listinfo/python-ideas

Arnaud Delobelle

unread,
Oct 3, 2008, 8:00:50 AM10/3/08
to Andreas Nilsson, python...@python.org
2008/10/3 Andreas Nilsson <ad...@trialcode.com>:

> Hi.
> I'm reposting this here after erroneously posting it on python-dev.
>
> I use list comprehensions and generator expressions a lot and lately I've
> found myself writing a lot of code like this:
>
> for i in items if i.some_field == some_value: i.do_something()

I'm pretty sure this has been proposed before and that the consensus
was that there was no advantage to writing:

for i in L if cond:
action()

instead of:

for i in L:
if cond: action()

--
Arnaud

Vitor Bosshard

unread,
Oct 3, 2008, 7:42:23 PM10/3/08
to Leif Walsh, python...@python.org

> On Fri, Oct 3, 2008 at 12:33 PM, Andreas Nilsson wrote:
> > Thanks for the pointer!
> > I don't buy the argument that newlines automagically improves readability
> > though. You also get increased nesting suggesting something interesting is
> > happening where it isn't and that hurts readability.
> > And as Vitor said, all other constructions of the form 'for i in items' can
> > have if-conditions attached to them, it's really not that far-fetched to
> > assume that the loop behaves the same way. Consistency good, surprises bad.
>
> Yeah, I know what you mean, and I kind of liked the idea of adding the
> if statement to the for loop (for consistency, if nothing else), but
> it's been discussed before, and plenty of people have made the same
> argument. Probably not worth it.

Besides consistency I think the one major benefit to for..if
loops is that often you don't just save a line, but also an indentation
level (whenever you use the if clause solely as a filter), which
actually increases readability, specially when whatever you do within
the loop is
relatively long, with its own indentations.


The syntax just feels natural. For example:

for i in somelist if i.pending:
<do stuff>


I really don't see any disadvantage here.

Vitor

PS: moving the discussion from python-dev to python-ideas.

____________________________________________________________________________________
¡Todo sobre Amor y Sexo!
La guía completa para tu vida en Mujer de Hoy.
http://mujerdehoy.telemundo.yahoo.com/

Arnaud Delobelle

unread,
Oct 10, 2008, 3:51:37 PM10/10/08
to Vitor Bosshard, python...@python.org

There is also a problem with parsing as:

* the following is correct:

for i in L1 if cond else L2:
do_something()

* Python's grammar is LL(1)

--
Arnaud

dbpo...@gmail.com

unread,
Oct 12, 2008, 2:38:35 PM10/12/08
to python...@python.org

On Oct 10, 12:51 pm, Arnaud Delobelle <arno...@googlemail.com> wrote:
> There is also a problem with parsing as:
>
> * the following is correct:
>
>      for i in L1 if cond else L2:
>         do_something()
>
> * Python's grammar is LL(1)

Not really.

for_stmt: 'for' exprlist 'in' testlist ['if' or_test] ':' suite
['else' ':' suite]

FWIW, I think this would be an entirely different discussion if
someone did all of the work first (code+docs+test code), and THEN went
to python-dev along with two or three examples from the standard
library where the new syntax would *add* clarity.

Side note: not to discourage anyone, but I happened to look at Lib/
pydoc.py and found several examples where, due to line-length, forcing
the new syntax at every available opportunity would either
substantially reduce clarity or be more or less pointless. Here are a
couple cases so you can make up you own mind.

#1

original:

for ext in ('.py', '.pyc', '.pyo'):
if os.path.isfile(os.path.join(path, '__init__' + ext)):
return True

vs. new syntax:

for ext in ('.py', '.pyc', '.pyo') if
os.path.isfile(os.path.join(path, '__init__' + ext)):
return True

vs. existing alternative:

if any( os.path.isfile(os.path.join(path,'__init__' + ext))
for ext in ('.py','.pyc','.pyo')):
return True

#2

original:

for dict in dicts:
if name in dict:
return '<a href="%s">%s</a>' % (dict[name], name)

new syntax:

for dict in dicts if name in dict:
return '<a href="%s">%s</a>' % (dict[name], name)

Cheers,
David

Arnaud Delobelle

unread,
Oct 12, 2008, 3:21:33 PM10/12/08
to dbpo...@gmail.com, python...@python.org
On 12 Oct 2008, at 19:38, dbpo...@gmail.com wrote:
>
> On Oct 10, 12:51 pm, Arnaud Delobelle <arno...@googlemail.com> wrote:
>> There is also a problem with parsing as:
>>
>> * the following is correct:
>>
>> for i in L1 if cond else L2:
>> do_something()
>>
>> * Python's grammar is LL(1)
>
> Not really.
>

What do you mean? Python's grammar is not LL(1)? Or Python + for-in-if
statements is still LL(1)?

> for_stmt: 'for' exprlist 'in' testlist ['if' or_test] ':' suite
> ['else' ':' suite]

What does that prove?

If I show you:

for i in L if

How do you know, without looking at further tokens, whether the 'if'
is part of an if-expression or part of a for-in-if statement?

--
Arnaud

dbpo...@gmail.com

unread,
Oct 12, 2008, 6:32:03 PM10/12/08
to python...@python.org
On Oct 12, 12:21 pm, Arnaud Delobelle <arno...@googlemail.com> wrote:

> On 12 Oct 2008, at 19:38, dbpoko...@gmail.com wrote:
>
>
>
> > On Oct 10, 12:51 pm, Arnaud Delobelle <arno...@googlemail.com> wrote:
> >> There is also a problem with parsing as:
>
> >> * the following is correct:
>
> >>      for i in L1 if cond else L2:
> >>         do_something()
>
> >> * Python's grammar is LL(1)
>
> > Not really.
>
> What do you mean? Python's grammar is not LL(1)? Or Python + for-in-if  
> statements is still LL(1)?

Oops! Here is what I should have said: if you replace

for_stmt: 'for' exprlist 'in' testlist ':' suite ['else' ':' suite]

in Grammar/Grammar with the following line

for_stmt: 'for' exprlist 'in' testlist_safe ['if' old_test] ':' suite
['else' ':' suite]

Then the grammar is still LL(1) since it resembles the LC syntax. I
neglected to turn the testlist into a testlist_safe. Now in theory
this could break code...it would break anything like

for x in my_list if some_condition else []:
...

Now this wouldn't even be a potential problem if Python converted to a
GLR parser, but that's another discussion.

>
> > for_stmt: 'for' exprlist 'in' testlist ['if' or_test] ':' suite
> > ['else' ':' suite]
>
> What does that prove?
>
> If I show you:
>
>     for i in L if
>
> How do you know, without looking at further tokens,  whether the 'if'  
> is part of an if-expression or part of a for-in-if statement?

You can say the same thing about an LC. The answer in that situation
is the last token ('if') maps to the first element of the right-hand
side of the list_if production.

David

Reply all
Reply to author
Forward
0 new messages