给出以下代码(不起作用):
while True:
#snip: print out current state
while True:
ok = get_input("Is this ok? (y/n)")
if ok == "y" or ok == "Y": break 2 #this doesn't work :(
if ok == "n" or ok == "N": break
#do more processing with menus and stuff
有没有办法让这项工作?或者我是否进行了一次检查以突破输入循环,然后另一个更有限的检查外部循环以在用户满意时将所有内容分开?
Edit-FYI: get_input是我编写的一个简短函数,它支持显示一个提示符和默认值以及所有那些幻想和返回 stdin.readline().strip()
28 回答
或类似的东西 . 您可以在内部循环中设置一个变量,并在内部循环退出后立即在外部循环中检查它,如果合适则中断 . 我有点像GOTO方法,只要你不介意使用愚人节的笑话模块 - 它不是Pythonic,但它确实有意义 .
PEP 3136建议标记为break / continue . Guido rejected it因为"code so complicated to require this feature is very rare" . PEP确实提到了一些变通方法(例如异常技术),而Guido认为在大多数情况下使用return的重构会更简单 .
将多个循环转换为单个可破坏循环的简单方法是使用
numpy.ndindex
你必须索引你的对象,而不是能够明确地迭代这些值,但至少在简单的情况下,它似乎比大多数建议的答案简单大约2-20倍 .
我的第一直觉是将嵌套循环重构为函数并使用
return
来突破 .类似于前一个,但更紧凑 . (布尔人只是数字)
如果不喜欢将refactorial转化为函数,那么下面可能会有一些小技巧
添加了1个break_level变量来控制while循环条件
By using a function:
尝试通过注释
return
来运行上述代码 .Without using any function:
现在,首先运行上面的代码然后尝试通过从底部一次注释掉包含
break
的每一行来运行 .将迭代减少到单级循环的另一种方法是通过使用python reference中指定的生成器
您可以将其扩展到循环的任意数量的级别
缺点是你不能再只打破一个级别 . 这是全有或全无 .
另一个缺点是它不适用于while循环 . 我最初想在Python -
break
out of all loops上发布这个答案,但遗憾的是,这个答案已经关闭了我来这里的原因是我有一个外循环和一个内循环,如下所示:
如您所见,它实际上不会转到下一个x,而是转到下一个y .
我发现解决这个问题的原因只是两次运行数组:
我知道这是OP问题的一个具体案例,但我发布它是希望它能帮助别人在保持简单的同时不同地思考他们的问题 .
在这种情况下,正如其他人所指出的那样,功能分解是要走的路 . Python 3中的代码:
首先,普通逻辑是有帮助的 .
如果由于某种原因无法解决终止条件,则例外是后备计划 .
对于此特定示例,可能不需要例外 .
另一方面,我们在字符模式应用程序中经常使用“Y”,“N”和“Q”选项 . 对于“Q”选项,我们希望立即退出 . 那更加特别 .
尝试使用无限发电机 .
Python
while ... else
结构中有一个隐藏的技巧,可以用来模拟双重中断而无需更改代码 . 实质上,如果while
条件为假,则触发else
块 . 两个例外,continue
或break
都不会触发else
块 . 有关更多信息,请参阅“Else clause on Python while statement”或Python doc on while (v2.7)的答案 .唯一的缺点是你需要将双重破坏条件移动到
while
条件(或添加一个标志变量) . 对于for
循环也存在这种变化,其中else
块在循环完成后被触发 .首先,您还可以考虑将输入的获取和验证过程作为一个功能;在该函数中,如果值正确则可以返回值,如果不正确则继续在while循环中旋转 . 这基本上消除了您解决的问题,并且通常可以应用于更一般的情况(打破多个循环) . 如果你绝对必须在你的代码中保留这个结构,并且真的不想处理簿记布尔...
您也可以通过以下方式使用goto(使用here中的April Fools模块):
我知道,我知道,“你不应该使用goto”等等,但它在这样的奇怪情况下效果很好 .
由于这个问题已成为打入特定循环的标准问题,我想用
Exception
给出我的答案 .虽然在多重循环结构中不存在名为break of loop的标签,但我们可以利用User-defined Exceptions进入我们选择的特定循环 . 考虑以下示例,让我们在base-6编号系统中打印最多4位数的所有数字:
当我们打印输出时,我们永远不会得到任何单位所在的值 . 在这种情况下,我们不会因为
BreakLoop(4)
被引发并被捕获到同一个循环而从任何循环中断 . 同样地,每当十个地方有3个时,我们使用BreakLoop(3)
进入第三个循环 . 每当百位有5,我们使用BreakLoop(2)
进入第二循环,当千位有2时,我们闯入第一循环使用BreakLoop(1)
.简而言之,在内部循环中提升您的异常(内置或用户定义),并在您想要恢复控制的循环中捕获它 . 如果要从所有循环中断,请在所有循环外捕获异常 . (我在示例中没有显示这种情况) .
我倾向于同意重构函数通常是这种情况的最佳方法,但是当你真的需要打破嵌套循环时,这里's an interesting variant of the exception-raising approach that @S.Lott described. It uses Python' s
with
语句使异常提升看起来更好一些 . 使用以下命令定义新的上下文管理器(您只需执行一次):现在您可以使用此上下文管理器,如下所示:
优点:(1)它稍微清洁(没有明确的try-except块),(2)每次使用
nested_break
时都会得到一个定制的Exception
子类;每次都不需要声明自己的Exception
子类 .我解决这个问题的方法是定义一个被引用的变量来确定你是否突破到了下一个级别 . 在此示例中,此变量称为“shouldbreak” .
这样可以很好地控制程序打破程度的准确程度,允许您选择何时打破以及打破多少级别 .
如果两个条件成立,为什么不保持循环?我认为这是一种更加pythonic的方式:
不是吗?
祝一切顺利 .
引入一个新变量,将其用作“循环断路器” . 首先为它指定一些东西(False,0等),然后,在外部循环中,在你从它中断之前,将值更改为其他值(True,1,...) . 循环退出后,“父”循环检查该值 . 让我来证明一下:
如果你有一个无限循环,这是唯一的出路;对于其他循环执行真的要快得多 . 如果您有许多嵌套循环,这也适用 . 你可以退出所有,或者只退出几个 . 无限可能!希望这有帮助!
要打破多个嵌套循环而不重构函数,请使用内置StopIteration exception的"simulated goto statement":
有关使用goto语句打破嵌套循环的信息,请参阅this discussion .
您可以定义一个变量(例如break_statement),然后在出现两个中断条件时将其更改为不同的值,并在if语句中将其用于从第二个循环中断 .
这是另一种简短的方法 . 缺点是你只能打破外循环,但有时它正是你想要的 .
(Bystander-EDIT在这里,因为我们在looong时间没见过@yak . )
关键见解:似乎外环总是断裂 . But if the inner loop doesn't break, the outer loop won't either.
continue
语句在这里很神奇 . 它在for-else子句中 . By definition如果没有内心突破就会发生这种情况 . 在那种情况下,continue
整齐地规避了外围的突破 .这不是最漂亮的方式,但在我看来,这是最好的方式 .
我很确定你也可以在这里使用递归来解决问题,但我不知道这对你来说是个不错的选择 .
我想提醒您,Python中的函数可以直接在代码中间创建,并且可以透明地访问周围的变量以进行读取,并使用
nonlocal
或global
声明进行编写 .因此,您可以将函数用作“可破坏的控件结构”,定义要返回的位置:
希望这会有所帮助:
将你的循环逻辑分解为一个迭代器,它产生循环变量并在完成后返回 - 这是一个简单的映射行/列的图像,直到我们没有图像或没有放置它们的地方:
这有利于拆分复杂的循环逻辑和处理......