flow control and nested loops
Raymond Hettinger
python at rcn.com
Sat Sep 26 06:35:57 EDT 2009
On Sep 25, 12:01 pm, kj <no.em... at please.post> wrote:
> In Perl, one can label loops for finer flow control. For example:
>
> X: for my $x (@X) {
> Y: for my $y (@Y) {
> for my $z (@Z) {
> next X if test1($x, $y, $z);
> next Y if test2($x, $y, $z);
> frobnicate($x, $y, $z);
> }
> glortz($x, $y);
> }
> splat($x);
>
> }
>
> What's considered "best practice" in the Python world for this sort
> of situation? The only approach I can think of requires setting
> up indicator variables that must be set and tested individually;
> e.g.
<snip>
> Whereas I find the Perl version reasonably readable, the Python
> one I find nearly incomprehensible. In fact, I'm not even sure
> that the Python version faithfully replicates what the Perl one is
> doing!
>
> Is there a better approach?
The Perl syntax is elegant and readable.
There is not a Python direct equivalent,
but then the situation doesn't come up often.
For the outermost loop, a break or continue suffices.
To exit multiple levels of loop, there a several choices
including try/except, flags, and functions with returns.
A try/except approach looks like this:
class NextX(Exception):pass
class NextY(Exception):pass
for x in X:
try:
for y in Y:
try:
for z in Z:
if test1(x,y,z):
raise NextX
if test2(x,y,z):
raise NextY
frobnicate(x,y,z)
except NextY: pass
except NextX: pass
Another approach for exiting multiple levels of loops is wrap the
inner calls in a function and return from them when needed:
def f(x):
for y in y:
for z in Z:
if test1(x,y,z):
return
frobnicate(x,y,z)
for x in X:
f(x)
Or you can write a little state machine with flags and a single loop
but that isn't very readable or satisfying.
Raymond
More information about the Python-list
mailing list