Control of flow

Paul Sidorsky paulsid at home.com
Tue Jul 31 14:07:15 EDT 2001


Campbell wrote:

> I use python to write telephony apps, and I find that a 'goto' is often
> a nice tool (stop going 'aargh', its properly "useful" sometimes =).

I disagree, it's evil and should be avoided at all costs!  :-)

> Here is a little snippet that gets a month/day from a caller.  If the
> day entered is not in the range of days valid for the month entered, we
> repeat from the top.  Does anyone have a few minutes to waste helping
> me??  How better can I code things that look like this:
> 
> >>> snip <<<
> while 1:
>     cont = 1         ## ugh!
>     month = getdtmf("enter2digs.vox", 2)
>     if month < 1 or month > 12:
>         play("invalidmonth.vox")
>         continue
>     while 1:
>         day = getdtmf("enterday", 2)
>         if day < 1 or day > Month[month]:
>             play("invalidday.vox")
>             cont = 1
>         cont = 0
>     if cont == 1:
>         continue
>     break
> >>> snip <<<

Your second loop will run indefinitely, and cont will always be 0. 
Unfortunately this bug (or pasting error?) makes it kind of hard to see exactly
what you want to do, but I'll take a shot at it.  (Two shots actually.)

If you always want to start back entering the month if the day was misentered,
this should work:

while 1:
    month = getdtmf("enter2digs.vox", 2)
    if month >= 1 and month <= 12:
        day = getdtmf("enterday", 2)
        if day >= 1 and day <= Month[month]:
            break #  Or another if statement should you need to do more.
        else:
            play("invalidday.vox")
    else:
        play("invalidmonth.vox")

This is very straightforward and easy to read even when nested heavily.

If, however, there are also times when just the day can be reentered (which is
the only reason I can see for needing the second loop in your example) then
you'll still control variables, but maybe this will be nicer:

dayvalid = 0
monthvalid = 0
while not monthvalid:
    month = getdtmf("enter2digs.vox", 2)
    if month >= 1 and month <= 12:
        monthvalid = 1
        while not dayvalid:
            day = getdtmf("enterday", 2)
            if day >= 1 and day <= Month[month]:
                dayvalid = 1
                break #  Or another if statement with a similar while loop.
            else:
                dayvalid = 0
                if needtostartoverwiththemonth:  ##
                    play("invalidday.vox")
                    monthvalid = 0
                    break
                else:
                    play("otherinvalidday.vox")  ##
    else:
        monthvalid = 0
        play("invalidmonth.vox")

(Lines with ## are pseudocodeish.)

With this approach you can quite easily back out of the loops to wherever you
need to start over.  For example, if you nested this further so you could get
an hour then a minute then some data, and if (for some reason) inputting
invalid data warranted restarting input at the day, you just set datavalid=0
and dayvalid=0 then break from the data loop and the other loops will do the
rest without any changes.  That is, minutevalid and hourvalid will be 1 so they
will terminate the minute and hour loops, leaving you back in the day loop
which will then start over because the day is no longer valid.

This approach does make for more long-winded code and more indents, but that's
a plus with hellish loop constructs.  When you need to look at it months later,
it's a lot easier to find a printer or screen that can display extra columns
than it is to find the team of programmers needed to figure out WTF you were
originally trying to do.  :-)

Does that help?  If not I hope you'll post more details and corrected code.

-- 
======================================================================
Paul Sidorsky                                          Calgary, Canada
paulsid at home.com                      http://members.home.net/paulsid/




More information about the Python-list mailing list