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

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

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


当前回答

通过使用函数:

def myloop():
    for i in range(1,6,1):  # 1st loop
        print('i:',i)
        for j in range(1,11,2):  # 2nd loop
            print('   i, j:' ,i, j)
            for k in range(1,21,4):  # 3rd loop
                print('      i,j,k:', i,j,k)
                if i%3==0 and j%3==0 and k%3==0:
                    return  # getting out of all loops

myloop()

尝试通过注释掉返回值来运行上面的代码。

不使用任何函数:

done = False
for i in range(1,6,1):  # 1st loop
    print('i:', i)
    for j in range(1,11,2):  # 2nd loop
        print('   i, j:' ,i, j)
        for k in range(1,21,4):  # 3rd loop
            print('      i,j,k:', i,j,k)
            if i%3==0 and j%3==0 and k%3==0:
                done = True
                break  # breaking from 3rd loop
        if done: break # breaking from 2nd loop
    if done: break     # breaking from 1st loop

现在,首先按原样运行上面的代码,然后尝试从底部注释掉包含break的每一行。

其他回答

首先,普通的逻辑是有用的。

如果由于某种原因,终止条件无法确定,例外是一个后备计划。

class GetOutOfLoop( Exception ):
    pass

try:
    done= False
    while not done:
        isok= False
        while not (done or isok):
            ok = get_input("Is this ok? (y/n)")
            if ok in ("y", "Y") or ok in ("n", "N") : 
                done= True # probably better
                raise GetOutOfLoop
        # other stuff
except GetOutOfLoop:
    pass

对于这个特定的示例,可能不需要异常。

另一方面,在字符模式应用程序中,我们经常有“Y”、“N”和“Q”选项。对于"Q"选项,我们要立即退出。这是比较特殊的。

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

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

引入一个新变量作为“循环打破器”。首先给它赋值(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   # <--- !

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

在Python中有一个隐藏的技巧…Else结构,可以用来模拟双中断,而不需要太多的代码更改/添加。本质上,如果while条件为false,则触发else块。任何异常、continue或break都不会触发else块。有关更多信息,请参阅对“Python while语句上的Else子句”或Python while上的doc (v2.7)的回答。

while True:
    #snip: print out current state
    ok = ""
    while ok != "y" and ok != "n":
        ok = get_input("Is this ok? (y/n)")
        if ok == "n" or ok == "N":
            break    # Breaks out of inner loop, skipping else

    else:
        break        # Breaks out of outer loop

    #do more processing with menus and stuff

唯一的缺点是需要将双中断条件移到while条件中(或添加一个标志变量)。对于for循环也存在这种变化,其中else块在循环完成后被触发。