flow control and nested loops

Simon Forman sajmikins at gmail.com
Fri Sep 25 22:06:46 CEST 2009


On Fri, Sep 25, 2009 at 3:01 PM, kj <no.email 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.
>
> for x in X:
>    next_X = False
>    for y in Y:
>        next_Y = False
>        for z in Z:
>            if test1(x, y, z):
>                next_X = True
>                break
>            if test2(x, y, z):
>                next_Y = True
>                break
>            frobnicate(x, y, z)
>        if next_X:
>            break
>        if next_Y:
>            continue
>        glortz(x, y)
>    if next_X:
>        continue
>    splat(x)
>
> 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?
>
> TIA!
>
> kynn
>

<snark>The best approach would be to reorganize your code so you
didn't have to do that.</snark>

Seriously though, I find both the perl and python versions
non-obvious.  You have had to use constructs like this in practice?

Generally, I would use "flags" in tricky nested loops just like you
did, perhaps with some comments to clarify things.   An alternative
might be to use custom exceptions.  Hopefully someone smarter than me
will come along and show an even better approach.


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:
                continue

            glortz(x, y)

    except NextX:
        continue

    splat(x)



More information about the Python-list mailing list