
I'd like to propose an addition to the for statement's syntax: for {variable} in {iterable} if {condition}: {block} which is equivalent to for {variable} in {iterable}: if not {condition}: continue {block} and for {variable} in filter(lambda: {condition}, iterable): {block} This would make the syntax closer to that of generators, which have 'for variable in iterable if condition', and would improve code clarity by increased brevity and not negating boolean expressions. Following are examples of current code with what the new code would be, taken from the Python 3.0a5 tarball. Demo/tkinter/guido/ss1.py:163: for (x, y), cell in self.cells.items(): if x <= 0 or y <= 0: continue for (x, y), cell in self.cells.items() if x > 0 and y > 0: Lib/encodings/__init__.py:91: for modname in modnames: if not modname or '.' in modname: continue for modname in modnames if modname and '.' not in modname: Lib/idlelib/AutoExpand.py:70: for w in wafter: if dict.get(w): continue for w in wafter if w not in dict: Lib/Cookie.py:483: for K,V in items: if V == "": continue if K not in attrs: continue for K,V in items if V != "" and K not in attrs: Lib/hashlib.py:108: for opensslFuncName in filter(lambda n: n.startswith('openssl_'), dir(_hashlib)): for opensslFuncName in dir(_hashlib) if opensslFuncName.startswith('openssl_'): There are many more examples of this in the standard library, and likely even more in production code. I am not familiar with LL(1) parsing, so this may impossible under that constraint.

First, the best list on which to discuss this would be Python-Ideas not Python-Dev. Second, this was brought up there a few months ago, although not much discussion ensued: http://mail.python.org/pipermail/python-ideas/2008-March/001407.html - Eli On Sun, May 18, 2008 at 9:45 PM, Ryan Hitchman <hitchmanr@gmail.com> wrote:
I'd like to propose an addition to the for statement's syntax:
for {variable} in {iterable} if {condition}: {block}
which is equivalent to
for {variable} in {iterable}: if not {condition}: continue {block}
and
for {variable} in filter(lambda: {condition}, iterable): {block}
This would make the syntax closer to that of generators, which have 'for variable in iterable if condition', and would improve code clarity by increased brevity and not negating boolean expressions.
Following are examples of current code with what the new code would be, taken from the Python 3.0a5 tarball.
Demo/tkinter/guido/ss1.py:163: for (x, y), cell in self.cells.items(): if x <= 0 or y <= 0: continue for (x, y), cell in self.cells.items() if x > 0 and y > 0:
Lib/encodings/__init__.py:91: for modname in modnames: if not modname or '.' in modname: continue for modname in modnames if modname and '.' not in modname:
Lib/idlelib/AutoExpand.py:70: for w in wafter: if dict.get(w): continue for w in wafter if w not in dict:
Lib/Cookie.py:483: for K,V in items: if V == "": continue if K not in attrs: continue for K,V in items if V != "" and K not in attrs:
Lib/hashlib.py:108: for opensslFuncName in filter(lambda n: n.startswith('openssl_'), dir(_hashlib)): for opensslFuncName in dir(_hashlib) if opensslFuncName.startswith('openssl_'):
There are many more examples of this in the standard library, and likely even more in production code.
I am not familiar with LL(1) parsing, so this may impossible under that constraint. _______________________________________________ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/eli%40courtwright.org

On Sun, 18 May 2008, Ryan Hitchman wrote:
I'd like to propose an addition to the for statement's syntax:
for {variable} in {iterable} if {condition}: {block}
which is equivalent to
for {variable} in {iterable}: if not {condition}: continue {block}
and
for {variable} in filter(lambda: {condition}, iterable): {block}
This would make the syntax closer to that of generators, which have 'for variable in iterable if condition', and would improve code clarity by increased brevity and not negating boolean expressions.
http://mail.python.org/pipermail/python-dev/2006-May/065090.html This was proposed and rejected before, after which it was again proposed and rejected. I think it was also proposed and rejected sometime in 2007, but I can't seem to find it in the archives so my memory may be faulty. The idea is apparently not dead yet. Hang around a couple of minutes, though. It won't be long. Isaac Morland CSCF Web Guru DC 2554C, x36650 WWW Software Specialist

for i in filter(lambda i: i%2, range(10)):
"Ryan Hitchman" <hitchmanr@gmail.com> wrote in message news:e60c31470805181845u7fb0cafdsb0878db491eb7a3c@mail.gmail.com... | I'd like to propose an addition to the for statement's syntax: | | for {variable} in {iterable} if {condition}: | {block} | | which is equivalent to | | for {variable} in {iterable}: | if not {condition}: | continue | {block} Is this different from for var in filter(lambda x: condition(x), iterable)): ? | and | | for {variable} in filter(lambda: {condition}, iterable): | {block} IDLE 3.0a5 print(i) 1 3 5 7 9

On Mon, May 19, 2008 at 5:55 AM, Terry Reedy <tjreedy@udel.edu> wrote:
"Ryan Hitchman" <hitchmanr@gmail.com> wrote in message news:e60c31470805181845u7fb0cafdsb0878db491eb7a3c@mail.gmail.com... | I'd like to propose an addition to the for statement's syntax: | | for {variable} in {iterable} if {condition}: | {block} | | which is equivalent to | | for {variable} in {iterable}: | if not {condition}: | continue | {block}
Is this different from for var in filter(lambda x: condition(x), iterable)): ?
| and | | for {variable} in filter(lambda: {condition}, iterable): | {block}
for i in filter(lambda i: i%2, range(10)):
IDLE 3.0a5 print(i)
1 3 5 7 9
How was it again? "One and only one way"? :-) -- Lennart Regebro: Zope and Plone consulting. http://www.colliberty.com/ +33 661 58 14 64

On Mon, 19 May 2008 08:42:29 pm Lennart Regebro wrote:
How was it again? "One and only one way"? :-)
Certainly not. What on earth gave you the idea that that ridiculous statement is a Python philosophy? I know some Perl developers like to contrast the supposed flexibility of Perl ("more than one way to do it") with the imagined poverty of Python, but that really is a silly claim to make about any Turing Complete language. If nothing else, any programming language that lets you perform arithmetic would not be so restrictive: x = (1+2)*3 + 3*3 x = (3+2)*3 + 1*3 Which one should the compiler prohibit? I strongly suggest that you look at the Zen of Python:
import this The Zen of Python, by Tim Peters ... There should be one-- and preferably only one --obvious way to do it.
There should be ONE OBVIOUS way to do it, not "only one way". -- Steven

On Mon, May 19, 2008 at 5:33 AM, Steven D'Aprano <steve@pearwood.info> wrote: ...
import this The Zen of Python, by Tim Peters ... There should be one-- and preferably only one --obvious way to do it.
There should be ONE OBVIOUS way to do it, not "only one way".
The "only one way" phrasing is in the "Spirit of C" section of the ISO C Standard `Rationale' (non-normative, but highly informative), specifically in point four, "provide only one way to do an operation". I contend that the somewhat different phrasing is somewhat accidental and not particularly relevant: the *intent* of this *language design guideline* is exactly the same (Tim was writing on his own, while the C Standard was written by a committee, so it's hardly surprising that the Standard's wording is drier and less funny than Tim's;-). IOW, I've often argued that this is a deep commonality between the design philosophy of C and Python (together with "trust the programmer" and "keep the language small and simple", two more points in the "Spirit of C" section) which makes them conceptually "closer" to each other than C is to languages sharing more of its syntax, from C++ to Javascript; it should be particularly easy to see the contrast with languages deliberately designed to provide multiple equivalent synonyms (such as foo.size and foo.length meaning the same thing in Ruby) or going out of their way to provide multiple equivalent syntax approaches for exactly the same semantics (such as Cobol's "ADD A TO B GIVING C" and "C = A + B", or SQL's explicit [INNER] JOIN form and the equivalent form where the inner join is left implicit in the WHERE clause). A design guideline is not a strict rule -- e.g., every C programmer has met situations where a while statement, and a for statement with some of the three subparts in the control clause omitted, can both make sense, and of course every time you write within your loop some "if(condition) continue" you wonder if in this case it might not be better to instead use "if(!condition) { ... }" around the rest of the loop's body, etc, etc -- so much for "only one way", as the various ways to perform elementary operations can click together in a large number of combinations and permutations; and adding "obvious" would not help much either, since both alternatives can easily happen to be "equally obvious". Python is just in the same situation. Nevertheless, keeping the guideline firmly in mind (e.g., eschewing synonyms in APIs you design that provide no added value beyond that of catering to different tastes or to a meta-taste for variety over uniformity;-) is still a helpful heuristic -- with or without the "obvious" word (i.e., whether you're working with C, which doesn't have the "obvious" in its phrasing of the principle, or with Python, which does). Alex

Ryan Hitchman wrote:
This would make the syntax closer to that of generators, which have 'for variable in iterable if condition',
Incorporating the filter condition into the list comprehension syntax (and later into generator expressions) is necessary because they need to be written as a single expression. The same doesn't hold true for loop filters: it is quite possible to keep the looping and filtering concerns separated into different statements, and there's no compelling reason for merging them.
would improve code clarity by increased brevity
Increased brevity != improved code clarity (in fact, being too terse can obfuscate things - just look at Perl)
not negating boolean expressions.
Except, of course, for those cases where it is easier to define the condition for items to skip than it is to define the condition for items to include.
Following are examples of current code with what the new code would be, taken from the Python 3.0a5 tarball.
Using just the standard idiom of a separate if statement to do the filtering: for (x, y), cell in self.cells.items(): if x <= 0 or y <= 0: continue # ... for modname in modnames: if not modname or '.' in modname: continue # ... for w in wafter: if dict.get(w): continue # ... for K,V in items: if V == "": continue if K not in attrs: continue # ... for opensslFuncName in dir(_hashlib): if opensslFuncName.startswith('openssl_'): continue # ... I'm not really seeing how the readability of any of those examples is enhanced by being able to merge the filter condition into the first line of the for loop. The one example which was already written that way through the use of filter() is actually easy to read with the addition of the vertical whitespace needed for the idiomatic form. The separate statement approach also scales far more cleanly to more complex filter conditions. For example, some code of mine includes a loop that looks like: for name in dirnames: if not os.path.exists(name): continue if not os.path.isdir(name): continue # Process named directory This conveys the order of checks far more clearly than would be the case if the os.path calls were hidden on the end of the loop invocation. Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia --------------------------------------------------------------- http://www.boredomandlaziness.org
participants (8)
-
Alex Martelli
-
Eli Courtwright
-
Isaac Morland
-
Lennart Regebro
-
Nick Coghlan
-
Ryan Hitchman
-
Steven D'Aprano
-
Terry Reedy