for / while else doesn't make sense

Ian Kelly ian.g.kelly at gmail.com
Tue Jun 7 00:35:33 EDT 2016


On Mon, Jun 6, 2016 at 6:51 PM, Lawrence D’Oliveiro
<lawrencedo99 at gmail.com> wrote:
> On Sunday, June 5, 2016 at 11:43:20 PM UTC+12, Marko Rauhamaa wrote:
>> I often experiment with different loop constructs to find the one most
>> pleasing to the eye. Working directly off iterators is quite rare but a
>> while-vs-for consideration is frequent. Also, should the stepping part
>> be in the beginning, middle or end of the loop body?
>
> It is nice to have a common, versatile looping form which can be arranged in different ways to suit the problem at hand. That’s why I like the C-style for-statement.
>
> Here’s another example <https://github.com/ldo/ipy_magics/blob/master/rman_magic.py>, for the consideration of those who don’t seem too familiar with looping:

A 500-line function? Yikes, what an eyesore. When you have to include
#end comments in order to visually match things up, that should be a
smell that your code is excessively complex. It took me a lot of
scrolling up and down just to figure out what the scopes of the
variables were.

>     while True :
>         while True :
>             line = next(input_line, None)
>             if line != None :
>                 if len(include_stack) == 0 :
>                     linenr += 1
>                 #end if
>                 break
>             #end if
>             if len(include_stack) == 0 :
>                 break
>             input_line = include_stack.pop()
>         #end while
>         if line == None or ... line contains something special ... :
>             ...
>             if line == None :
>                 break
>             ... process special line ...
>             ... replace with None to indicate it’s been processed ...
>         #end if
>         if line != None :
>             ... process regular line ...
>         #end if
>     #end while

    def generate_lines():
        nonlocal input_line
        while True:
            try:
                # Note input_line appears to be an iterator, not a string
                # as suggested by the name.
                yield next(input_line)
            except StopIteration:
                if include_stack:
                    input_line = include_stack.pop()
                else:
                    return

    for line in generate_lines():
        if not include_stack:
            linenr += 1
        if ... line contains something special ...:
            ... process special line ...
        else:
            ... process regular line ...

Much simpler than the nested while loop hell above, and not a single
break needed (if you don't count the return, that is; in any case each
loop has a single exit point). I'd be tempted to refactor input_line
and include_stack into some sort of input context class and make
generate_lines a method of the class in order to avoid having those
variables be (effectively) global, but my goal was to keep this as
close to the original in design as possible.


More information about the Python-list mailing list