Mat*_*ley 440 python break control-flow
给出以下代码(不起作用):
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
Run Code Online (Sandbox Code Playgroud)
有没有办法让这项工作?或者我是否已经做了一次检查以突破输入循环,然后另一个更有限的检查外部循环以在用户满意的情况下将所有内容分开?
Edit-FYI: get_input是我编写的一个简短函数,支持显示提示和默认值以及所有那些幻想和返回__CODE__
Rob*_*ney 457
我的第一直觉是将嵌套循环重构为函数并用于return突破.
小智 193
这是另一种简短的方法.缺点是你只能打破外循环,但有时它正是你想要的.
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
Run Code Online (Sandbox Code Playgroud)
这使用了for/else构造解释:为什么python在for和while循环之后使用'else'?
关键见解:似乎外环总是断裂.但是如果内部循环没有破坏,外部循环也不会.
该continue声明是这里的神奇.它在for-else子句中.根据定义,如果没有内部中断,就会发生这种情况.在那种情况下,continue整齐地绕开了外围的突破.
Joh*_*uhy 144
PEP 3136提出标记的中断/继续.Guido 拒绝了它,因为"代码如此复杂,需要此功能非常罕见".PEP确实提到了一些解决方法(例如异常技术),而Guido认为在大多数情况下使用return的重构会更简单.
S.L*_*ott 108
首先,普通逻辑是有帮助的.
如果由于某种原因,终止条件无法解决,例外是一个后备计划.
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
Run Code Online (Sandbox Code Playgroud)
对于此特定示例,可能不需要例外.
另一方面,我们在字符模式应用程序中经常使用"Y","N"和"Q"选项.对于"Q"选项,我们希望立即退出.这更加特殊.
Mar*_*son 51
我倾向于同意重构函数通常是这种情况的最佳方法,但是当你真的需要打破嵌套循环时,这是@ S.Lott描述的异常提升方法的有趣变体.它使用Python的with语句使异常提升看起来更好一些.使用以下命令定义新的上下文管理器(您只需执行一次):
from contextlib import contextmanager
@contextmanager
def nested_break():
class NestedBreakException(Exception):
pass
try:
yield NestedBreakException
except NestedBreakException:
pass
Run Code Online (Sandbox Code Playgroud)
现在您可以使用此上下文管理器,如下所示:
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"
Run Code Online (Sandbox Code Playgroud)
优点:(1)它稍微清洁(没有明确的try-except块),以及(2)你Exception为每次使用获得一个定制的子类nested_break; Exception每次都不需要声明自己的子类.
Mat*_*t J 38
首先,您还可以考虑将输入的获取和验证过程作为一个函数; 在该函数中,如果值正确则可以返回值,如果不正确则继续在while循环中旋转.这基本上消除了您解决的问题,并且通常可以应用于更一般的情况(打破多个循环).如果你绝对必须在你的代码中保留这个结构,并且真的不想处理簿记布尔...
您也可以通过以下方式使用goto(使用此处的愚人节模块):
#import the stuff
from goto import goto, label
while True:
#snip: print out current state
while True:
ok = get_input("Is this ok? (y/n)")
if ok == "y" or ok == "Y": goto .breakall
if ok == "n" or ok == "N": break
#do more processing with menus and stuff
label .breakall
Run Code Online (Sandbox Code Playgroud)
我知道,我知道,"你不应该使用goto"等等,但它在这样的奇怪情况下效果很好.
小智 29
引入一个新变量,将其用作"循环断路器".首先为它指定一些东西(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 # <--- !
Run Code Online (Sandbox Code Playgroud)
如果你有一个无限循环,这是唯一的出路; 对于其他循环执行真的要快得多.如果您有许多嵌套循环,这也适用.你可以退出所有,或只退出几个.无限可能!希望这有帮助!
Jus*_*tas 17
要打破多个嵌套循环而不重构函数,请使用带有内置StopIteration异常的"模拟goto语句" :
try:
for outer in range(100):
for inner in range(100):
if break_early():
raise StopIteration
except StopIteration: pass
Run Code Online (Sandbox Code Playgroud)
见这个讨论关于使用goto语句的嵌套循环的突破.
qui*_*dry 15
keeplooping=True
while keeplooping:
#Do Stuff
while keeplooping:
#do some other stuff
if finisheddoingstuff(): keeplooping=False
Run Code Online (Sandbox Code Playgroud)
或类似的东西.你可以在内部循环中设置一个变量,并在内部循环退出后立即在外部循环中检查它,如果合适则中断.我有点像GOTO方法,只要你不介意使用愚人节的笑话模块 - 它不是Pythonic,但它确实有意义.
Jas*_*ker 12
这不是最漂亮的方式,但在我看来,这是最好的方式.
def loop():
while True:
#snip: print out current state
while True:
ok = get_input("Is this ok? (y/n)")
if ok == "y" or ok == "Y": return
if ok == "n" or ok == "N": break
#do more processing with menus and stuff
Run Code Online (Sandbox Code Playgroud)
我很确定你也可以在这里使用递归来解决问题,但我不知道这对你来说是个不错的选择.
Muh*_*eed 12
从语言层面来说是没有办法做到这一点的。有些语言有 goto,其他语言有带参数的中断,但 python 没有。
最好的选择是:
设置一个由外循环检查的标志,或设置外循环条件。
将循环放入函数中,然后使用 return 立即跳出所有循环。
重新表述你的逻辑。
使用功能
def doMywork(data):
for i in data:
for e in i:
return
Run Code Online (Sandbox Code Playgroud)
使用标志
is_break = False
for i in data:
if is_break:
break # outer loop break
for e in i:
is_break = True
break # inner loop break
Run Code Online (Sandbox Code Playgroud)
如果两个条件成立,为什么不保持循环?我认为这是一种更加pythonic的方式:
dejaVu = True
while dejaVu:
while True:
ok = raw_input("Is this ok? (y/n)")
if ok == "y" or ok == "Y" or ok == "n" or ok == "N":
dejaVu = False
break
Run Code Online (Sandbox Code Playgroud)
不是吗?
祝一切顺利.
小智 8
将循环逻辑分解为一个迭代器,它产生循环变量并在完成时返回 - 这是一个简单的循环变量,它在行/列中排列图像,直到我们没有图像或者放置它们的地方:
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 ...
Run Code Online (Sandbox Code Playgroud)
这有利于分割复杂的循环逻辑和处理......
将多个循环转变为单个可破坏循环的简单方法是使用numpy.ndindex
for i in range(n):
for j in range(n):
val = x[i, j]
break # still inside the outer loop!
for i, j in np.ndindex(n, n):
val = x[i, j]
break # you left the only loop there was!
Run Code Online (Sandbox Code Playgroud)
您确实必须对对象进行索引,而不是能够显式地迭代值,但至少在简单的情况下,它似乎比大多数建议的答案简单大约 2-20 倍。
Python 结构中有一个隐藏的技巧while ... else,可以用来模拟双中断,而无需更改/添加太多代码。本质上,如果while条件为假,else则触发块。既不异常,continue也不break触发else块。有关更多信息,请参阅“ Python while 语句上的 Else 子句”的答案,或while (v2.7) 上的 Python 文档。
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
Run Code Online (Sandbox Code Playgroud)
唯一的缺点是您需要将双重中断条件移至条件中while(或添加标志变量)。循环也存在这种变化for,其中else块在循环完成后被触发。
| 归档时间: |
|
| 查看次数: |
351430 次 |
| 最近记录: |