给定以下代码(不起作用):
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
有办法解决这个问题吗?还是我必须先检查一次,跳出输入循环,然后再检查一次,如果用户满意,再跳出外部循环?
我倾向于认为重构到函数中通常是这种情况的最佳方法,但是当您确实需要打破嵌套循环时,这里有一个有趣的异常引发方法的变体@S。洛特。它使用Python的with语句使异常引发看起来更好一些。定义一个新的上下文管理器(你只需要这样做一次):
from contextlib import contextmanager
@contextmanager
def nested_break():
class NestedBreakException(Exception):
pass
try:
yield NestedBreakException
except NestedBreakException:
pass
现在你可以像下面这样使用这个上下文管理器:
with nested_break() as mylabel:
while True:
print "current state"
while True:
ok = raw_input("Is this ok? (y/n)")
if ok == "y" or ok == "Y": raise mylabel
if ok == "n" or ok == "N": break
print "more processing"
优点:(1)它稍微干净一些(没有显式的try-except块),并且(2)每次使用nested_break你都会得到一个定制的Exception子类;不需要每次都声明自己的Exception子类。
解决方法有两种
举个例子:这两个矩阵相等/相同吗?
矩阵x1和矩阵x2是相同大小的,n,二维矩阵。
第一个解决方案,没有函数
same_matrices = True
inner_loop_broken_once = False
n = len(matrix1)
for i in range(n):
for j in range(n):
if matrix1[i][j] != matrix2[i][j]:
same_matrices = False
inner_loop_broken_once = True
break
if inner_loop_broken_once:
break
第二个解决方案,用函数
这是我案子的最终解决方案。
def are_two_matrices_the_same (matrix1, matrix2):
n = len(matrix1)
for i in range(n):
for j in range(n):
if matrix1[i][j] != matrix2[i][j]:
return False
return True
在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块在循环完成后被触发。
如果您只需要在复杂的for循环巢中测试边缘情况,则可以抛出1/0来引发异常。我保证不会告诉任何人。当您希望快速测试深度嵌套的for循环的单个迭代,并且不想跟踪大量break语句或注释掉大量代码时,这种方法非常方便。
是的,您可以将它包装在函数中并使用return,但在某些上下文中,这可能会非常麻烦。
入门级程序员的例子:
for i in first_iter:
for j in second_iter:
for k in third_iter:
print(i_want_to_run_this_once_and_stop_executing(i,j,k))
1/0
code_that_takes_a_long_time()
expensive_code()
在执行大量数据预处理的大型jupyter笔记本脚本中,这尤其方便。
你可以使用一个标志来打破循环:
if found:
break
这里,'found'是标志,你最初将它设置为False,然后在循环中使用这段代码。
found = False
for table_height in range(500):
if found:
break
下面是三个for循环的完整代码:
found = False
for table_height in range(500):
if found:
break
for cat_height in range(500):
if found:
break
for tort_height in range(500):
equation1 = table_height + cat_height == tort_height + 170
equation2 = table_height + tort_height == cat_height + 130
if equation1 and equation2:
print('table', table_height, ' cat', cat_height, ' tortoise', tort_height)
found = True
break
在这段代码中,如果等式1和等式2为True,它将设置'found'标志为True,并跳出最里面的for循环,它也将跳出其他两个for循环,因为'found'为True。