[Python-ideas] for/else statements considered harmful

Nick Coghlan ncoghlan at gmail.com
Thu Jun 7 15:36:08 CEST 2012


On Thu, Jun 7, 2012 at 11:06 PM, Alice Bevan–McGregor
<alice at gothcandy.com> wrote:
> On 2012-06-07 00:53:22 +0000, Nick Coghlan said:
>>
>>    for x in range(20):
>>        if x > 10:
>>            break
>>    except break:
>>        # Bailed out early
>>    else:
>>        # Reached the end of the loop
>
>
> Seems a not insignifigant number of readers got fixated on the alternate
> keyword for the current behaviour of else (finally in my example) and
> ignored or misinterpreted the -really important part- of being able to
> detect if the loop was skipped (no iterations performed; else in my
> example).
>
> Being able to have a block executed if the loop is never entered is vitally
> important so you can avoid expensive or potentially impossible length checks
> on the iterator before the loop.  Take this example:
>
>   sock = lsock.accept()
>   for chunk in iter(partial(sock.recv, 4096), ''):
>       pass # do something with the chunk
>   else:
>       pass # no data recieved before client hangup!
>
> Using a temporary varable to simulate this is… unfortunate.
>
>   sock = lsock.accept()
>   has_data = False
>   for chunk in iter(partial(sock.recv, 4096), ''):
>       has_data = True
>       pass # do something with the chunk
>
>   if not has_data:
>       pass # no data recieved before client hangup!
>
> empty woud be a good keyword to preserve the existing meaning of else, but
> I'm pretty sure that's a fairly common variable name.  :/

Yeah, it's usually fairly important on here to separate out "this is
the problem I see" from "this is a proposed solution". Getting
agreement on the former is usually easier than the latter, since there
are so many additional constraints that come into play when it comes
to considering solutions. And if we can't even reach agreement that a
problem needs to be solved, then talking about solution details isn't
especially productive (although it can be fun to speculate about the
possibilities anyway).

FWIW, I usually solve this particular problem with for loops by using
the iteration variable itself to hold a sentinel value:

   sock = lsock.accept()
   chunk = None
   for chunk in iter(partial(sock.recv, 4096), ''):
       pass # do something with the chunk

   if chunk is None:
       pass # no data recieved before client hangup!

If "None" is a possible value in the iterable, then I'll use a
dedicated sentinel value instead:

    var = sentinel = object()
    for var in iterable:
        ...
    if var is sentinel:
        ...

I've never found either of those constructs ugly enough to
particularly want dedicated syntax to replace it, and the availability
of this approach is what makes it especially difficult to push for
dedicated syntactic support (since all that can really be saved is the
assignment that sets up the sentinel value).

Cheers,
Nick.

-- 
Nick Coghlan   |   ncoghlan at gmail.com   |   Brisbane, Australia



More information about the Python-ideas mailing list