给定以下代码(不起作用):

while True:
    # Snip: print out current state
    while True:
        ok = get_input("Is this ok? (y/n)")
        if ok.lower() == "y": break 2 # This doesn't work :(
        if ok.lower() == "n": break

    # Do more processing with menus and stuff

有办法解决这个问题吗?还是我必须先检查一次,跳出输入循环,然后再检查一次,如果用户满意,再跳出外部循环?


当前回答

# this version breaks up to a certain label

break_label = None
while True:
    # snip: print out current state
    while True:
        ok = get_input("Is this ok? (y/n)")
        if ok == "y" or ok == "Y":
            break_label = "outer"   # specify label to break to
            break
        if ok == "n" or ok == "N":
            break
    if break_label:
        if break_label != "inner":
            break                   # propagate up
        break_label = None          # we have arrived!
if break_label:
    if break_label != "outer":
        break                       # propagate up
    break_label = None              # we have arrived!

#do more processing with menus and stuff

其他回答

将循环逻辑分解为迭代器,迭代器产生循环变量并在完成时返回——这里有一个简单的迭代器,它将图像按行/列排列,直到我们用完图像或找不到放置它们的位置:

def it(rows, cols, images):
    i = 0
    for r in xrange(rows):
        for c in xrange(cols):
            if i >= len(images):
                return
            yield r, c, images[i]
            i += 1 

for r, c, image in it(rows=4, cols=4, images=['a.jpg', 'b.jpg', 'c.jpg']):
    ... do something with r, c, image ...

这样做的优点是将复杂的循环逻辑和处理分开。

要跳出多个嵌套循环,而不需要重构为函数,可以使用带有内置StopIteration异常的“模拟goto语句”:

try:
    for outer in range(100):
        for inner in range(100):
            if break_early():
                raise StopIteration

except StopIteration: pass

请参阅使用goto语句打破嵌套循环的讨论。

# this version uses a level counter to choose how far to break out

break_levels = 0
while True:
    # snip: print out current state
    while True:
        ok = get_input("Is this ok? (y/n)")
        if ok == "y" or ok == "Y":
            break_levels = 1        # how far nested, excluding this break
            break
        if ok == "n" or ok == "N":
            break                   # normal break
    if break_levels:
        break_levels -= 1
        break                       # pop another level
if break_levels:
    break_levels -= 1
    break

# ...and so on

希望这能有所帮助:

x = True
y = True
while x == True:
    while y == True:
         ok = get_input("Is this ok? (y/n)") 
         if ok == "y" or ok == "Y":
             x,y = False,False #breaks from both loops
         if ok == "n" or ok == "N": 
             break #breaks from just one

以下是一个非常简短的版本: 创建名为break_out_nested.py的文件

import itertools
import sys

it = sys.modules[__name__] # this allows us to share variables with break_out_nested.py when we import it 


def bol(*args):
    condi = args[-1] # the condition function
    i = args[:-1] # all iterables 
    for p in itertools.product(*i): # itertools.product creates the nested loop
        if condi(): # if the condition is True, we return 
            return
        yield p # if not, we yield the result 

现在你只需要几行就可以打破嵌套的循环(数据来自Rafiq的例子)

from break_out_nested import it, bol # import what we have just created

# you need to create new variables as attributes of it,
# because break_out_nested has only access to these variables
it.i, it.j, it.k = 1, 1, 1
# the break condition
def cond(): return it.i % 3 == 0 and it.j % 3 == 0 and it.k % 3 == 0

# The condition will be checked in each loop 
for it.i, it.j, it.k in bol(range(1, 6, 1), range(1, 11, 2, ), range(1, 21, 4), cond):
    print(it.i, it.j, it.k)

更多的例子:

def cond(): return it.i + it.j + it.k == 777

it.i, it.j, it.k = 0, 0, 0
for it.i, it.j, it.k in bol(range(100), range(1000), range(10000), cond):
    print(it.i, it.j, it.k)




def cond(): return it.i + it.j + it.k >= 100000

it.i, it.j, it.k = 0, 0, 0
# you dont have to use it.i, it.j, it.k as the loop variables, you can
# use anything you want, but you have to update the variables somewhere
for i, j, k in bol(range(100), range(1000), range(10000), cond):
    it.i, it.j, it.k = i * 10, j * 100, k * 100
    print(it.i, it.j, it.k)