[Python-ideas] for/else syntax
Antti Rasinen
ars at iki.fi
Fri Oct 2 08:05:00 CEST 2009
On 2009-10-02, at 06:07, Steven D'Aprano wrote:
> On Thu, 1 Oct 2009 09:00:21 pm Antti Rasinen wrote:
>
>> To add further insult to the naming injury, the else branch suffers
>> from the fact that 99.9% of the time, the for-loop contains an if:
>
> Really? You've done a statistically significant survey of code in the
> wild and come to a figure accurate to one part in a thousand? Not just
> plucked a number straight out of thin air?
>
> In my code, the figure is more like 20-40%. Choosing one
> representative
> module at random, only one in three for-loops include an if inside the
> loop. And when I use for...else, it's closer to 10%.
Oh silly me. I used some sloppy language there. I did not mean that
all for-loops have ifs inside them. What does your last statistic
mean? Do you have if statements in only 10% of your for..else loops or
in 10% of your all for-loops (including for...else)? If you mean the
first case, then please ignore the rest of this message and post an
example :-)
What I meant that most *for...else* structures have an if inside. The
99.9% number is, as you say, plucked from thin air -- but I think it
is very close to the truth. There are simpler alternatives to
for..else if the loop does not contain an if. Consider the following
structure:
for x in xs:
# body
else:
# else-branch
If you don't have a break in the body of the for-loop, then you don't
need the else: at all. You can write the above segment as:
for x in xs:
# body
# else-branch
If, on the other hand, you do have a break in the body, then either it
is conditional or it is not. If there is no break, then you are either
only processing the first element in the iterable or skipping directly
to the else branch. In this case it would be natural to use plain if:
if xs:
# body with xs[0]
# else-branch
Iterators complicate the matter, but even in that case then I'd rather
use a peeking wrapper around xs.
It seems to me that the only sensible use case for for..else is when
there is an conditional break inside the loop. I'll appreciate any
counter examples, of course.
Nick Coghlan's had a lovely example about search loops earlier in the
thread. It also highlights one of the reasons why I think the
for..else construct is so rare. Consider his example:
for obj in iterable:
if found_it(obj):
# Found what we were looking for!
break
else:
# It wasn't there :(
There are several ways of writing this without for..else. If the
context for the loop is correct, you might just use return True (or
obj) during the loop. No need for an else-branch there.
Or you might use any:
if not any(found_it(obj) for obj in iterable):
# It wasn't there :(
It seems to me that there often are "more intuitive" ways of writing a
for..else-loop. And accordingly, the construct is rare. I'll resort to
some newspeak here and define "intuitive" as either "conveys the
intent of the programmer better" or as "feels like the more obvious
way to do it". Pick either.
--Antti
--
[ ars at iki.fi <*> Antti Rasinen ]
This drone-vessel speaks with the voice and authority of the Ur-Quan.
More information about the Python-ideas
mailing list