Python 如何打破多个循环?
给定以下代码(不起作用):Python 如何打破多个循环?,python,nested-loops,break,control-flow,Python,Nested Loops,Break,Control Flow,给定以下代码(不起作用): 有没有办法让这一切顺利进行?或者,如果用户满意,我是否必须进行一次检查以中断输入循环,然后进行另一次更有限的检查,以在外部循环中一起中断?首先,普通逻辑很有用 如果由于某种原因,终止条件无法确定,则例外情况为后备计划 class GetOutOfLoop( Exception ): pass try: done= False while not done: isok= False while not (done
有没有办法让这一切顺利进行?或者,如果用户满意,我是否必须进行一次检查以中断输入循环,然后进行另一次更有限的检查,以在外部循环中一起中断?首先,普通逻辑很有用 如果由于某种原因,终止条件无法确定,则例外情况为后备计划
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”选项,我们希望立即退出。这是比较特殊的。 首先,您也可以考虑获取和验证输入函数的过程;在该函数中,只要返回正确的值,如果不正确,就可以在while循环中继续旋转。这从本质上消除了您解决的问题,通常可以应用于更一般的情况(打破多个循环)。如果您绝对必须在代码中保留此结构,并且确实不想处理簿记布尔值 您还可以通过以下方式使用goto(使用来自的愚人节模块):
我知道,我知道,“你不应该使用goto”等等,但它在这种奇怪的情况下工作得很好。我的第一反应是将嵌套循环重构成一个函数,然后使用
return
来中断
keeplooping=True
while keeplooping:
#Do Stuff
while keeplooping:
#do some other stuff
if finisheddoingstuff():
keeplooping=False
keeploping=True
在继续浏览时:
#做事
在继续浏览时:
#做些别的事情
如果完成DdoingStuff():
keeploping=False
或者类似的。您可以在内部循环中设置一个变量,并在内部循环退出后立即在外部循环中检查它,如果合适,可以中断。我有点喜欢GOTO方法,只要你不介意使用愚人节的笑话模块——它不是Pythonic,但它确实有意义。这不是最漂亮的方法,但在我看来,这是最好的方法
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
我敢肯定,您也可以在这里使用递归解决一些问题,但我不知道这是否适合您。建议使用“中断/继续”。Guido是因为“代码如此复杂以至于需要这个特性是非常罕见的”。不过,政治公众人物确实提到了一些变通方法(如异常技术),虽然Guido认为重构使用return在大多数情况下会更简单。将循环逻辑分解成迭代器,迭代器生成循环变量并在完成时返回——下面是一个简单的方法,它将图像按行/列排列,直到我们没有图像或放不下它们:
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 ...
这样做的好处是可以将复杂的循环逻辑和处理过程分开…这里还有另一种简单的方法。缺点是你只能打破外部循环,但有时这正是你想要的
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构造,解释如下:
关键洞察:似乎只有外环总是断裂但如果内循环不中断,外循环也不会中断。
def doMywork(data):
for i in data:
for e in i:
return
continue
语句是这里的神奇之处。在for else条款中。如果没有内部破裂,就会发生这种情况。在这种情况下,continue
巧妙地避开了外部中断。我倾向于同意,对于这种情况,重构成函数通常是最好的方法,但是对于真正需要中断嵌套循环的情况,这里有一个@s.Lott描述的异常引发方法的有趣变体。它使用Python的with
语句使异常引发看起来更好一些。使用以下工具定义新的上下文管理器(您只需执行一次):
现在,您可以按如下方式使用此上下文管理器:
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)它稍微干净一些(除了块之外没有显式的尝试),并且(2)每次使用
嵌套的_break
都会得到一个定制的异常
子类;无需每次都声明自己的异常
子类。引入一个新变量,用作“循环断路器”。首先给它赋值(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 # <--- !
breaker=False#我们强大的循环退出!
尽管如此:
尽管如此:
如果满足条件:
#在这里插入代码。。。
断路器=真
打破
if breaker:#有趣的部分!
break#与之前的类似,但更紧凑。
(布尔只是数字)
breaker=False#我们强大的循环退出!
尽管如此:
尽管如此:
ok=获取输入(“这可以吗?(y/n)”)
断路器+=(正常。下降()=“y”)
打破
if breaker:#有趣的部分!
break#我来这里的原因是我有一个外环和一个内环,就像这样:
for x in array:
for y in dont_use_these_values:
if x.value==y:
array.remove(x) # fixed, was array.pop(x) in my original answer
continue
do some other stuff with x
如您所见,它实际上不会转到下一个x,而是转到下一个y
我发现要解决这个问题,只需在数组中运行两次:
for x in array:
for y in dont_use_these_values:
if x.value==y:
array.remove(x) # fixed, was array.pop(x) in my original answer
continue
for x in array:
do some other stuff with x
我知道这是OP问题的一个具体案例,但我发布它是希望它能帮助人们在保持简单的同时以不同的方式思考他们的问题。如果两个条件都是真的,为什么不继续循环呢?
我认为这是一种更具python风格的方式:
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
不是吗
祝您一切顺利。尝试使用无限生成器
from itertools import repeat
inputs = (get_input("Is this ok? (y/n)") for _ in repeat(None))
response = (i.lower()=="y" for i in inputs if i.lower() in ("y", "n"))
while True:
#snip: print out current state
if next(response):
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
Python中有一个隐藏的技巧,而。。。else
结构,可用于模拟双断点,无需大量代码更改/添加。本质上,如果while
条件为false,则触发else
块。任何异常,continue
或break
都不会触发else
b
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
from itertools import repeat
inputs = (get_input("Is this ok? (y/n)") for _ in repeat(None))
response = (i.lower()=="y" for i in inputs if i.lower() in ("y", "n"))
while True:
#snip: print out current state
if next(response):
break
#do more processing with menus and stuff
# this version uses a level counter to choose how far to break out
break_levels = 0
while True:
# snip: print out current state
while True:
ok = get_input("Is this ok? (y/n)")
if ok == "y" or ok == "Y":
break_levels = 1 # how far nested, excluding this break
break
if ok == "n" or ok == "N":
break # normal break
if break_levels:
break_levels -= 1
break # pop another level
if break_levels:
break_levels -= 1
break
# ...and so on
# 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 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
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
break_level = 0
# while break_level < 3: # if we have another level of nested loop here
while break_level < 2:
#snip: print out current state
while break_level < 1:
ok = get_input("Is this ok? (y/n)")
if ok == "y" or ok == "Y": break_level = 2 # break 2 level
if ok == "n" or ok == "N": break_level = 1 # break 1 level
for i, j in ((i, j) for i in A for j in B):
print(i , j)
if (some_condition):
break
while True:
break_statement=0
while True:
ok = raw_input("Is this ok? (y/n)")
if ok == "n" or ok == "N":
break
if ok == "y" or ok == "Y":
break_statement=1
break
if break_statement==1:
break
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
x = True
y = True
while x == True:
while y == True:
ok = get_input("Is this ok? (y/n)")
if ok == "y" or ok == "Y":
x,y = False,False #breaks from both loops
if ok == "n" or ok == "N":
break #breaks from just one
try:
for outer in range(100):
for inner in range(100):
if break_early():
raise StopIteration
except StopIteration: pass
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
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!
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
def doMywork(data):
for i in data:
for e in i:
return
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
while True:
#snip: print out current state
quit = False
while True:
ok = input("Is this ok? (y/n)")
if ok.lower() == "y":
quit = True
break # this should work now :-)
if ok.lower() == "n":
quit = True
break # This should work too :-)
if quit:
break
#do more processing with menus and stuff