I thought a bit about Carl's and Thomas' proposals, and it gave me an idea how this problem could be approached: Break is relatively easy to implement with a context manager that returns an iterable that throws an exception specific to that context manager:
with named_loop(i for i in range(10)) as loop1: for i in loop1: with named_loop(i for i in range(10)) as loop2a: for j in loop2a: loop1._break() # this is easy loop1._continue() # this is difficult # if we _continue here, we need to do a continue right after the with loop2a: if loop1.cont: continue # context manager does not create new scope with named_loop(i for i in range(10)) as loop2b: for j in loop2b: loop1._break() this throws an exception that propagates through all the context managers till it hits the one that made loop1 at that point the exception is caught. Now using the idea of break_levels, something like loop1._continue() should work. It is more difficult, because it should be caught in the last loop before the one that is targeted, loop1._continue throws an exception that is caught in loop2. Then loop1 just continues with the next value. I don't know how loop2 can learn that it is enclosed in loop1. Maybe loop1 could add itself to a global stack on enter and delete itself on exit, or maybe inspect could help? The big problem is that loop1._continue breaks out of loop2a, but then starts to execute loop2b, which we don't want. If loop1 is _continued inside of loop2a, a continue needs to directly follow the loop2a with block. An alternative would be to wrap each sequence of statements in another with statement, I think this is better: for i in loop1: with sequenced_stuff(): with named_loop(i for i in range(10)) as loop2a: for j in loop2a: loop1._continue() # this is caught in sequenced_stuff() with named_loop(i for i in range(10)) as loop2b: for j in loop2b: loop1._break() Loops can even be restarted with a small modification: In a loop like "for i in loop1:" the __iter__ method of loop1 is called. If __iter__ returns a smart iterator that keeps a reference to loop1, then it can be restarted, advanced etc. loop1.restart() would throw an exception that __exits__ all the inner loops and gets caught in the loop just before loop1. Then it resets the iterable that the iterator returned by __iter__ links to, i.e. loop1 restarts. Nice side benefit: loops can have a method peek(n) to look ahead. Thanks for all your input, Dan -- http://mail.python.org/mailman/listinfo/python-list