打破嵌套循环

有没有比抛出异常更简单的方法来打破嵌套循环?(在Perl中,您可以为每个循环提供标签,并至少继续一个外部循环。)

for x in range(10):
for y in range(10):
print x*y
if x*y > 50:
"break both loops"

也就是说,有没有比以下更好的方法:

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
533031 次浏览

它至少已经被建议,但也拒绝了。除了重复测试或重新组织代码之外,我不认为还有其他方法。这有时有点烦人。

被拒绝的消息中,van Rossum先生提到使用return,这是非常明智的,也是我个人需要记住的东西。:)

在这种特殊情况下,您可以使用itertools.product将循环与现代python(3.0,也可能是2.6)合并。

对于我自己来说,这是一个经验法则,如果你嵌套了太多的循环(比如,超过2个),你通常能够将其中一个循环提取到一个不同的方法中,或者将循环合并为一个,就像在这种情况下。

您还可以重构代码以使用生成器。但这可能不是所有类型的嵌套循环的解决方案。

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

这同样适用于更深层次的循环:

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

如果能够将循环代码提取到函数中,则可以使用return语句随时退出最外层的循环。

def foo():
for x in range(10):
for y in range(10):
print(x*y)
if x*y > 50:
return
foo()

如果很难提取该函数,则可以使用内部函数,如@bjd2385所建议的那样。

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()
...

有时我使用布尔变量。如果你想说幼稚的话,但我觉得这本书读起来很灵活,很舒服。测试一个变量可以避免再次测试复杂的条件,还可以从内部循环中的几个测试中收集结果。

    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

使用itertools.product !

from itertools import product
for x, y in product(range(10), range(10)):
#do whatever you want
break

这是itertools的链接。python文档中的产品: http://docs.python.org/library/itertools.html#itertools.product < / p >

你也可以循环一个包含2个for的数组理解,并在任何你想要的时候中断。

>>> [(x, y) for y in ['y1', 'y2'] for x in ['x1', 'x2']]
[
('x1', 'y1'), ('x2', 'y1'),
('x1', 'y2'), ('x2', 'y2')
]

如果你要引发异常,你可能会引发抛出StopIteration异常。这至少会让意图变得明显。