Op 02-09-13 10:05, Steven D'Aprano schreef: > On Sun, 01 Sep 2013 21:58:15 +0200, Antoon Pardon wrote: > >> Op 31-08-13 02:09, Steven D'Aprano schreef: > >>> Adding a fourth option: >>> >>> for spam in sequence if predicate(spam): >>> process(spam) >>> >>> saves absolutely nothing except a line and an indent level, neither of >>> which are in short supply, and gains nothing in readability over Option >>> 1. >> >> So what is the big difference between this situation and the following: >> >> | else: >> | if condition: >> | whatever >> >> which in python we can write: >> >> | elif condition: >> | whatever >> >> >> So either is seems this was a design mistake or a line and an indent >> level can be important enough to allow a combination of controls. > > > The difference is that elif is syntax for chaining potentially large > numbers of else if clauses: > > if a: > else: > if b: > else: > if c: > else: > if d: > else: > > It's not uncommon to have, say, a dozen separate elif clauses. Put that > inside a method inside a class and you've got an indent of 56 spaces > inside the final else block. But that's not really the problem, the real > problem is that repeated nesting like this obscures the fact that it is a > chain of if...if...if...if and all the if's really should be at the same > indentation level.
> In contrast, you never need to write something like this: > > for item in seq: if a: if b: if c: if d: ... > > since that's better written as > > for item in seq: if a and b and c and d: > > So a "filtered for" only includes a single if clause. Multiple if clauses > don't match the "one line or two" scenario: > > for item in seq: if cond: <block> elif predicate: <block> else: <block> > > is not an option. With a single if, filtering the for loop, this is an > option: > > # with or without the first colon > for item in seq: if cond: > <block> > > versus: > > for item in seq: > if cond: > <block> > > What's the benefit of the first version? It doesn't make it any more > obvious that the for is being filtered. It makes that just as obvious as using an elif makes it obvious we are having a chain of ifs. It is not obvious because it can be logically deduced, but is is obvious by how programmic idioms start occuring. Just as people sometime prefer | else: | if ... If they think that illustrates the decision process more clearly people could chose whether to use the combined or seperated controls depending on whether they considered the if as the filter part of an iterator or as an independ decision proces. > It doesn't keep a whole chain of > if clauses together. It doesn't let you do anything that you haven't > already done. It just saves an indent and a newline. The cost, on the > other hand, includes the risk that people will try to do this: > > for item in seq: if cond: > do_this() > do_that() > else: > do_something else() > > which is clearly nonsense. Worse is this: > > for item in seq: if cond: > do_this() > do_that() > else: > do_something else() > > which is still nonsense but won't raise SyntaxError. Why shouldn't this raise a SyntaxError? > It would be a Bad Thing if adding a legal else clause to a legal if > clause caused a syntax error. But we are not necessarily talking about an if clause, we can be talking about an iterator with a filter attached, or about a combined control. > But the only way to prevent that is to > prohibit the for...if one line version in the first place. No it isn't. > *None* of these objections apply to the list comp version of for, where > the "block" consists of a single statement before the "for". So despite a > superficial (very superficial) similarity between > > [expr for item in seq if filter] > > and > > for item in seq if filter: > expr > > I believe that Python is right to allow the first and prohibit the second. Fine, at this point I'll think we'll just have to agree to disagree. -- Antoon Pardon -- http://mail.python.org/mailman/listinfo/python-list