Plays with using try/raise to break out of nested loops.

This is inspired by Travis Risner's play_break.py, but is much cruder than his code and has significant differences in kind from his code.

  • exception does not return (this is probably the biggest difference)
  • matches on a tuple
  • exception is an argument
  • range(2) for smaller example output

This was fun to play with, but this variable level break stuff makes my head hurt. So it is probably a bad idea. One should probably rearrange the code some other way. What real world application can you think of where this kind of code is the simplest, most succinct, easiest to read solution?


In [1]:
class FirstLevelBreak(Exception): pass
class SecondLevelBreak(Exception): pass
class ThirdLevelBreak(Exception): pass

def show_break(level, i, x_y_z):
    print(
        '    ',
        'Broke with i={} at x,y,z = {} ({} level) '.format(
        i,
        x_y_z,
        level))

def foo(limit, exception):
    print()
    print('foo(limit=%r, exception=%r)' % (limit, exception))
    i = 0
    try:
        for x in range(2):
            try:
                for y in range(2):
                    try:
                        for z in range(2):
                            print('    ', (x,y,z))
                            if (x,y,z) == limit:
                                raise exception
                            i += 1
                    except ThirdLevelBreak:
                        show_break('third', i, (x,y,z))
            except SecondLevelBreak:
                show_break('second', i, (x,y,z))
    except FirstLevelBreak:
        show_break('first', i, (x,y,z))
    print('exiting with i=%s, x,y,z=%s' % (i, (x,y,z)))
    return i, (x,y,z)

In [2]:
foo((0, 0, 0), ThirdLevelBreak)
foo((0, 0, 0), SecondLevelBreak)
foo((0, 0, 0), FirstLevelBreak)
foo((1, 0, 0), ThirdLevelBreak)
foo((1, 0, 0), SecondLevelBreak)
foo((1, 0, 0), FirstLevelBreak)
foo((None, None, None), None)


foo(limit=(0, 0, 0), exception=<class '__main__.ThirdLevelBreak'>)
     (0, 0, 0)
     Broke with i=0 at x,y,z = (0, 0, 0) (third level) 
     (0, 1, 0)
     (0, 1, 1)
     (1, 0, 0)
     (1, 0, 1)
     (1, 1, 0)
     (1, 1, 1)
exiting with i=6, x,y,z=(1, 1, 1)

foo(limit=(0, 0, 0), exception=<class '__main__.SecondLevelBreak'>)
     (0, 0, 0)
     Broke with i=0 at x,y,z = (0, 0, 0) (second level) 
     (1, 0, 0)
     (1, 0, 1)
     (1, 1, 0)
     (1, 1, 1)
exiting with i=4, x,y,z=(1, 1, 1)

foo(limit=(0, 0, 0), exception=<class '__main__.FirstLevelBreak'>)
     (0, 0, 0)
     Broke with i=0 at x,y,z = (0, 0, 0) (first level) 
exiting with i=0, x,y,z=(0, 0, 0)

foo(limit=(1, 0, 0), exception=<class '__main__.ThirdLevelBreak'>)
     (0, 0, 0)
     (0, 0, 1)
     (0, 1, 0)
     (0, 1, 1)
     (1, 0, 0)
     Broke with i=4 at x,y,z = (1, 0, 0) (third level) 
     (1, 1, 0)
     (1, 1, 1)
exiting with i=6, x,y,z=(1, 1, 1)

foo(limit=(1, 0, 0), exception=<class '__main__.SecondLevelBreak'>)
     (0, 0, 0)
     (0, 0, 1)
     (0, 1, 0)
     (0, 1, 1)
     (1, 0, 0)
     Broke with i=4 at x,y,z = (1, 0, 0) (second level) 
exiting with i=4, x,y,z=(1, 0, 0)

foo(limit=(1, 0, 0), exception=<class '__main__.FirstLevelBreak'>)
     (0, 0, 0)
     (0, 0, 1)
     (0, 1, 0)
     (0, 1, 1)
     (1, 0, 0)
     Broke with i=4 at x,y,z = (1, 0, 0) (first level) 
exiting with i=4, x,y,z=(1, 0, 0)

foo(limit=(None, None, None), exception=None)
     (0, 0, 0)
     (0, 0, 1)
     (0, 1, 0)
     (0, 1, 1)
     (1, 0, 0)
     (1, 0, 1)
     (1, 1, 0)
     (1, 1, 1)
exiting with i=8, x,y,z=(1, 1, 1)
Out[2]:
(8, (1, 1, 1))