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

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

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


当前回答

希望这能有所帮助:

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

其他回答

引入一个新变量作为“循环打破器”。首先给它赋值(False,0等),然后,在外层循环中,在终止它之前,将值更改为其他值(True,1,…)。一旦循环退出,让“父”循环检查该值。让我来演示一下:

breaker = False #our mighty loop exiter!
while True:
    while True:
        if conditionMet:
            #insert code here...
            breaker = True 
            break
    if breaker: # the interesting part!
        break   # <--- !

如果你有一个无限循环,这是唯一的出路;对于其他循环,执行速度要快得多。如果你有很多嵌套循环,这也适用。你可以退出全部,也可以只退出一部分。无尽的可能性!希望这对你有所帮助!

由于这个问题已经成为进入特定循环的标准问题,我想用Exception给出我的答案。

虽然在多循环构造中不存在名为“循环中断”的标签,但我们可以使用用户定义异常来中断到我们选择的特定循环。考虑下面的例子,让我们在6进制编号系统中打印所有最多4位的数字:

class BreakLoop(Exception):
    def __init__(self, counter):
        Exception.__init__(self, 'Exception 1')
        self.counter = counter

for counter1 in range(6):   # Make it 1000
    try:
        thousand = counter1 * 1000
        for counter2 in range(6):  # Make it 100
            try:
                hundred = counter2 * 100
                for counter3 in range(6): # Make it 10
                    try:
                        ten = counter3 * 10
                        for counter4 in range(6):
                            try:
                                unit = counter4
                                value = thousand + hundred + ten + unit
                                if unit == 4 :
                                    raise BreakLoop(4) # Don't break from loop
                                if ten == 30: 
                                    raise BreakLoop(3) # Break into loop 3
                                if hundred == 500:
                                    raise BreakLoop(2) # Break into loop 2
                                if thousand == 2000:
                                    raise BreakLoop(1) # Break into loop 1

                                print('{:04d}'.format(value))
                            except BreakLoop as bl:
                                if bl.counter != 4:
                                    raise bl
                    except BreakLoop as bl:
                        if bl.counter != 3:
                            raise bl
            except BreakLoop as bl:
                if bl.counter != 2:
                    raise bl
    except BreakLoop as bl:
        pass

当我们打印输出时,我们永远不会得到任何单位位是4的值。在这种情况下,在同一个循环中引发BreakLoop(4)并捕获时,我们不会中断任何循环。类似地,当十位有3时,我们使用BreakLoop(3)进入第三个循环。当百位是5时,我们使用BreakLoop(2)进入第二个循环,当千位是2时,我们使用BreakLoop(1)进入第一个循环。

简而言之,在内部循环中引发异常(内置或用户定义),并在循环中从您想恢复控件的位置捕获它。如果想从所有循环中中断,可以在所有循环之外捕获异常。(我没有举例说明)。

尝试使用无限发电机。

from itertools import repeat
inputs = (get_input("Is this ok? (y/n)") for _ in repeat(None))
response = (i.lower()=="y" for i in inputs if i.lower() in ("y", "n"))

while True:
    #snip: print out current state
    if next(response):
        break
    #do more processing with menus and stuff

希望这能有所帮助:

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