Collectives™ on Stack Overflow
Find centralized, trusted content and collaborate around the technologies you use most.
Learn more about Collectives
Teams
Q&A for work
Connect and share knowledge within a single location that is structured and easy to search.
Learn more about Teams
I wanted to know if there are any built-in ways to continue to next iteration in outer loop in python. For example, consider the code:
for ii in range(200):
for jj in range(200, 400):
...block0...
if something:
continue
...block1...
I want this continue statement to exit the jj loop and goto next item in the ii loop. I can implement this logic in some other way (by setting a flag variable), but is there an easy way to do this, or is this like asking for too much?
–
–
–
–
–
–
–
–
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):
continue_i = ContinueI()
for i in ...:
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.
–
–
–
In other languages you can label the loop and break from the labelled loop. Python Enhancement Proposal (PEP) 3136 suggested adding these to Python but Guido rejected it:
However, I'm rejecting it on the basis that code so complicated to
require this feature is very rare. In most cases there are existing
work-arounds that produce clean code, for example using 'return'.
While I'm sure there are some (rare) real cases where clarity of the
code would suffer from a refactoring that makes it possible to use
return, this is offset by two issues:
The complexity added to the language, permanently. This affects not
only all Python implementations, but also every source analysis tool,
plus of course all documentation for the language.
My expectation that the feature will be abused more than it will be
used right, leading to a net decrease in code clarity (measured across
all Python code written henceforth). Lazy programmers are everywhere,
and before you know it you have an incredible mess on your hands of
unintelligible code.
So if that's what you were hoping for you're out of luck, but look at one of the other answers as there are good options there.
–
–
–
–
–
–
–
We want to find something and then stop the inner iteration. I use a flag system.
for l in f:
flag = True
for e in r:
if flag==False:continue
if somecondition:
do_something()
flag=False
–
–
–
I think one of the easiest ways to achieve this is to replace "continue" with "break" statement,i.e.
for ii in range(200):
for jj in range(200, 400):
...block0...
if something:
break
...block1...
For example, here is the easy code to see how exactly it goes on:
for i in range(10):
print("doing outer loop")
print("i=",i)
for p in range(10):
print("doing inner loop")
print("p=",p)
if p==3:
print("breaking from inner loop")
break
print("doing some code in outer loop")
Another way to deal with this kind of problem is to use Exception()
.
for ii in range(200):
for jj in range(200, 400):
...block0...
if something:
raise Exception()
except Exception:
continue
...block1...
For example:
for n in range(1,4):
for m in range(1,4):
print n,'-',m
result:
Assuming we want to jump to the outer n loop from m loop if m =3:
for n in range(1,4):
for m in range(1,4):
if m == 3:
raise Exception()
print n,'-',m
except Exception:
continue
result:
Reference link:http://www.programming-idioms.org/idiom/42/continue-outer-loop/1264/python
I just did something like this. My solution for this was to replace the interior for loop with a list comprehension.
for ii in range(200):
done = any([op(ii, jj) for jj in range(200, 400)])
...block0...
if done:
continue
...block1...
where op is some boolean operator acting on a combination of ii and jj. In my case, if any of the operations returned true, I was done.
This is really not that different from breaking the code out into a function, but I thought that using the "any" operator to do a logical OR on a list of booleans and doing the logic all in one line was interesting. It also avoids the function call.
The best approach I know to continue an outer loop is using a Boolean that is scoped under the outer loop and breaking the inner one. Although, depending on the use case you may not break the inner loop, continuing an outer loop inside its inner loop implicitly suggests that you want to immediately jump to the first line of the outer loop and avoid any further execution in the inner one. That is why I added a break
statement.
for i in range(0, 6):
should_continue = False
for f in range(1, i * 2):
print(f"f = {f}")
if (not (f % 1337) or not (f % 7)):
print(f"{f} can be divided, continue outer loop")
should_continue = True
# leaves inner loop
break
if(should_continue): continue
# Outer loop's code goes here
print(f'Reached outer loop\ni = {i}')
This approach avoids calling any functions and dealing with possible drawbacks. Calling a function is known to be a rather expensive operation, specially for Games. Now imagine a deeply nested for
loop that will run millions of times, wrapping it inside a function won't result in a smooth experience.
Wrapping the loop inside an exception block is also a bad idea and will be way slower than functions. This is because Python needs a lot of overhead to trigger the exceptions mechanism and later restore the runtime state, exceptions are designed to be used exceptionally. Taking that in mind, even some CPU optimizations such as speculative execution
should not be applied to exception blocks and probably aren't.
The only "problem" I found in this approach is that break
will jump once outside of the inner loop, landing on continue
, which, in turn, will jump one more time. This, as opposed to a goto statement in C or JavaScript, is a bit more clumsy, but doesn't have any visible impact in performance, because it would generate only one extra instruction that runs as fast as your CPU's clock or as the interpreter implementation.