flow control and nested loops

Raymond Hettinger python at rcn.com
Sat Sep 26 12:35:57 CEST 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.
> 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:
         for y in Y:
             for z in Z:
                 if test1(x,y,z):
                     raise NextX
                 if test2(x,y,z):
                     raise NextY
           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):

   for x in X:

Or you can write a little state machine with flags and a single loop
but that isn't very readable or satisfying.


More information about the Python-list mailing list