## 问题：Python：继续外循环中的下一个迭代

``````for ii in range(200):
for jj in range(200, 400):
...block0...
if something:
continue
...block1...``````

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?

## 回答 0

``````for i in ...:
for j in ...:
for k in ...:
if something:
# continue loop i``````

## 将您想转义的循环重构为一个函数

``````def inner():
for j in ...:
for k in ...:
if something:
return

for i in ...:
inner()``````

``````for i in ...:
def inner():
for j in ...:
for k in ...:
if something:
return
inner()``````

## 使用exceptions

``````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``````

## 完全其他的东西

``````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.

## 回答 1

``````for ii in range(200):
for jj in range(200, 400):
...block0...
if something:
break
else:
...block1...``````

`Break` 将中断内部循环，并且不会执行block1（仅在内部循环正常退出时才会运行）。

``````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).

## 回答 2

1. 复杂性永久地增加了语言。这不仅会影响所有Python实现，而且会影响每个源代码分析工具，当然还会影响该语言的所有文档。

2. 我期望该功能的滥用程度将超过其正确使用的程度，从而导致代码清晰度净下降（此后对所有编写的Python代码进行衡量）。懒惰的程序员无处不在，在您不了解它之前，您就难以理解难以理解的代码。

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:

1. 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.

2. 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.

## 回答 3

``````for ii in range(200):
restart = False
for jj in range(200, 400):
...block0...
if something:
restart = True
break
if restart:
continue
...block1...``````

I think you could do something like this:

``````for ii in range(200):
restart = False
for jj in range(200, 400):
...block0...
if something:
restart = True
break
if restart:
continue
...block1...
``````

## 回答 4

``````for ii in range(200):
for jj in range(200, 400):
...block0...
if something:
break
...block1...       ``````

``````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")``````

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")
``````

## 回答 5

``````for ii in range(200):
try:
for jj in range(200, 400):
...block0...
if something:
raise Exception()
except Exception:
continue
...block1...``````

``````for n in range(1,4):
for m in range(1,4):
print n,'-',m``````

``````    1-1
1-2
1-3
2-1
2-2
2-3
3-1
3-2
3-3``````

``````for n in range(1,4):
try:
for m in range(1,4):
if m == 3:
raise Exception()
print n,'-',m
except Exception:
continue``````

``````    1-1
1-2
2-1
2-2
3-1
3-2``````

Another way to deal with this kind of problem is to use Exception().

``````for ii in range(200):
try:
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:

``````    1-1
1-2
1-3
2-1
2-2
2-3
3-1
3-2
3-3
``````

Assuming we want to jump to the outer n loop from m loop if m =3:

``````for n in range(1,4):
try:
for m in range(1,4):
if m == 3:
raise Exception()
print n,'-',m
except Exception:
continue
``````

result:

``````    1-1
1-2
2-1
2-2
3-1
3-2
``````

## 回答 6

``````for l in f:
flag = True
for e in r:
if flag==False:continue
if somecondition:
do_something()
flag=False``````

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
``````

## 回答 7

``````for ii in range(200):
done = any([op(ii, jj) for jj in range(200, 400)])
...block0...
if done:
continue
...block1...``````

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.