My first instinct would be to refactor the nested loop into a function and use return to break out.
Videos
My first instinct would be to refactor the nested loop into a function and use return to break out.
Here's another approach that is short. The disadvantage is that you can only break the outer loop, but sometimes it's exactly what you want.
for a in range(10):
for b in range(20):
if something(a, b):
break # Break the inner loop...
else:
continue # Continue if the inner loop wasn't broken.
break # Inner loop was broken, break the outer.
This uses the for / else construct explained at: Why does python use 'else' after for and while loops?
Key insight: It only seems as if the outer loop always breaks. But if the inner loop doesn't break, the outer loop won't either.
The continue statement is the magic here. It's in the for-else clause. By definition that happens if there's no inner break. In that situation continue neatly circumvents the outer break.
for ii in range(200):
for jj in range(200, 400):
...block0...
if something:
break
else:
...block1...
Break will break the inner loop, and block1 won't be executed (it will run only if the inner loop is exited normally).
for i in ...:
for j in ...:
for k in ...:
if something:
# continue loop i
In a general case, when you have multiple levels of looping and break does not work for you (because you want to continue one of the upper loops, not the one right above the current one), you can do one of the following
Refactor the loops you want to escape from into a function
def inner():
for j in ...:
for k in ...:
if something:
return
for i in ...:
inner()
The disadvantage is that you may need to pass to that new function some variables, which were previously in scope. You can either just pass them as parameters, make them instance variables on an object (create a new object just for this function, if it makes sense), or global variables, singletons, whatever (ehm, ehm).
Or you can define inner as a nested function and let it just capture what it needs (may be slower?)
for i in ...:
def inner():
for j in ...:
for k in ...:
if something:
return
inner()
Use exceptions
Philosophically, this is what exceptions are for, breaking the program flow through the structured programming building blocks (if, for, while) when necessary.
The advantage is that you don't have to break the single piece of code into multiple parts. This is good if it is some kind of computation that you are designing while writing it in Python. Introducing abstractions at this early point may slow you down.
Bad thing with this approach is that interpreter/compiler authors usually assume that exceptions are exceptional and optimize for them accordingly.
class ContinueI(Exception):
pass
continue_i = ContinueI()
for i in ...:
try:
for j in ...:
for k in ...:
if something:
raise continue_i
except ContinueI:
continue
Create a special exception class for this, so that you don't risk accidentally silencing some other exception.
Something else entirely
I am sure there are still other solutions.