Breaking out of nested loops
Possible Duplicate:
How to break out of multiple loops in Python?
有没有比抛出异常更容易脱离嵌套循环的方法?(在Perl中,您可以为每个循环提供标签,并且至少继续一个外部循环。)
1 2 3 4 5 | for x in range(10): for y in range(10): print x*y if x*y > 50: "break both loops" |
也就是说,有没有比以下更好的方法:
1 2 3 4 5 6 7 8 9 10 | class BreakIt(Exception): pass try: for x in range(10): for y in range(10): print x*y if x*y > 50: raise BreakIt except BreakIt: pass |
1 2 3 4 5 6 7 8 | for x in xrange(10): for y in xrange(10): print x*y if x*y > 50: break else: continue # only executed if the inner loop did NOT break break # only executed if the inner loop DID break |
同样适用于更深的回路:
1 2 3 4 5 6 7 8 9 10 11 12 | for x in xrange(10): for y in xrange(10): for z in xrange(10): print x,y,z if x*y*z == 30: break else: continue break else: continue break |
它至少被建议过,但也被拒绝了。我认为除了重复测试或重新组织代码之外,没有其他方法。有时候有点烦人。
在拒绝信中,范罗森提到使用
如果能够将循环代码提取到函数中,那么可以随时使用
1 2 3 4 5 6 7 | def foo(): for x in range(10): for y in range(10): print x*y if x*y > 50: return foo() |
如果很难提取该函数,则可以使用内部函数,如@bjd2385所建议的。
1 2 3 4 5 6 7 8 9 10 | def your_outer_func(): ... def inner_func(): for x in range(10): for y in range(10): print x*y if x*y > 50: return inner_func() ... |
使用itertools.product!
1 2 3 4 | from itertools import product for x, y in product(range(10), range(10)): #do whatever you want break |
下面是python文档中指向itertools.product的链接:http://docs.python.org/library/itertools.html itertools.product
您还可以循环一个数组理解,其中包含2个fors,并在需要时中断。
1 2 3 4 5 | >>> [(x, y) for y in ['y1', 'y2'] for x in ['x1', 'x2']] [ ('x1', 'y1'), ('x2', 'y1'), ('x1', 'y2'), ('x2', 'y2') ] |
(为清晰起见格式化)
有时我使用布尔变量。天真,如果你愿意的话,但我觉得阅读起来相当灵活和舒适。测试一个变量可以避免再次测试复杂的条件,也可以从内部循环的几个测试中收集结果。
1 2 3 4 5 6 7 8 | x_loop_must_break = False for x in range(10): for y in range(10): print x*y if x*y > 50: x_loop_must_break = True break if x_loop_must_break: break |
如果要引发异常,可能会引发StopIteration异常。这至少会使意图变得明显。
还可以重构代码以使用生成器。但这可能不是所有类型的嵌套循环的解决方案。
在这种特殊情况下,可以使用itertools.product将循环与现代的python(3.0,也可能是2.6)合并。
我个人认为这是一个经验法则,如果你嵌套了太多的循环(如中,多于2个),你通常能够将其中一个循环提取到不同的方法中,或者将循环合并到一个方法中,就像在本例中那样。