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

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

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


当前回答

在这种情况下,正如其他人指出的那样,功能分解是可行的方法。Python 3中的代码:

def user_confirms():
    while True:
        answer = input("Is this OK? (y/n) ").strip().lower()
        if answer in "yn":
            return answer == "y"

def main():
    while True:
        # do stuff
        if user_confirms():
            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)进入第一个循环。

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

keeplooping = True
while keeplooping:
    # Do stuff
    while keeplooping:
          # Do some other stuff
          if finisheddoingstuff():
              keeplooping = False

或者类似的东西。

您可以在内部循环中设置一个变量,并在内部循环退出后立即在外部循环中检查它,如果合适的话可以中断。我有点喜欢GOTO方法,前提是你不介意使用愚人节的笑话模块——它不是python的,但它确实有意义。

这是另一种简短的方法。缺点是你只能打破外部循环,但有时这正是你想要的。

for a in xrange(10):
    for b in xrange(20):
        if something(a, b):
            # Break the inner loop...
            break
    else:
        # Continue if the inner loop wasn't broken.
        continue
    # Inner loop was broken, break the outer.
    break

这使用了for / else结构:为什么python在for和while循环之后使用'else' ?

关键洞见:似乎只有外部循环总是会破裂。但如果内环不破裂,外环也不会破裂。

这里的continue语句很神奇。它在for-else从句中。根据定义,如果没有内部断裂,就会发生这种情况。在这种情况下,继续巧妙地绕过外部中断。

我想提醒你,Python中的函数可以在代码中间创建,并且可以透明地访问周围的变量以进行读取,也可以通过非局部或全局声明进行写入。

所以你可以使用一个函数作为“易碎的控制结构”,定义一个你想要返回的地方:

def is_prime(number):

    foo = bar = number

    def return_here():
        nonlocal foo, bar
        init_bar = bar
        while foo > 0:
            bar = init_bar
            while bar >= foo:
                if foo*bar == number:
                    return
                bar -= 1
            foo -= 1

    return_here()

    if foo == 1:
        print(number, 'is prime')
    else:
        print(number, '=', bar, '*', foo)

>>> is_prime(67)
67 is prime
>>> is_prime(117)
117 = 13 * 9
>>> is_prime(16)
16 = 4 * 4

尽量减少对OP的问题的改变,我只是在打破第一个for循环之前添加了一个标志,并检查外部循环上的标志,看看我们是否需要再次刹车。

break_2 = False
while True:
    # Snip: print out current state
    if break_2: break
    while True:
        ok = get_input("Is this ok? (y/n)")
        if ok.lower() == "y": break_2 = True
        if break_2: break
        if ok.lower() == "n": break
    # Do more processing with menus and stuff