Control of flow
Robert Amesz
reqhye72zux at mailexpire.com
Tue Jul 31 19:15:25 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 =).
>
> 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 <<<
I'm not a 100% sure what this code is supposed to do, but I'll grant
you this: it is butt-ugly, and looks like its logic is dodgy. Just look
at the beginning and end of the loop:
while 1:
cont = 1 ## ugh!
<statements>
if cont == 1:
continue
break
This looks fairly redundant as
cont = 1
while cont:
<statements>
will do *exactly* the same thing, and it's more efficient too.
Certainly the 'ugh!' factor is reduced considerably this way.
How your app is supposed to leave the inner while 1: loop isn't clear,
so I'll assume some crucial code has been omitted for this example.
So how would I write this code? Well, I'll assume the following
behaviour is required:
1 - Get a valid month and day
2 - When invalid numbers are entered: start form scratch
Which yields:
while 1:
# Get month
month = getdtmf("enter2digs.vox", 2)
if month < 1 or month > 12:
play("invalidmonth.vox")
continue # Bad month, start from scratch
# Get day
day = getdtmf("enterday", 2)
if (day >= 1) and (day <= DaysInMonth[month]):
break # Done!
# Bad day...
play("invalidday.vox")
# ...start from scratch
[Note: I've changed the name of the 'Month'-sequence into DaysInMonth,
because it's a better name. I presume it has been precalculated for a
particular year, although it might be better to make it into a function
like
DaysInMonth(month, year)
or
DaysInMonth(month, isLeapYear) ]
A goto isn't needed for code like this, nor would a goto make it look
any clearer. For more complex control flow problems it is sometimes
advisable to break up code into separate functions and use 'return' to
break out of those functions. Use exceptions if you need to break out
of nested function calls.
What sometimes *does* happen is that you find that the interaction
between the human and the machine are modelled better by a finite-state
automaton: complex protocols are often described this way. It wouldn't
be too hard to make a general state machine in Python, but I'll leave
that as an excercise to the reader. ;-)
Robert Amesz
More information about the Python-list
mailing list