打破嵌套循环

Mic*_*uhn 250 python loops

可能重复:
如何在Python中打破多个循环?

是否有一种更容易的方法来打破嵌套循环而不是抛出异常?(在Perl中,您可以为每个循环指定标签,并至少继续外循环.)

for x in range(10):
    for y in range(10):
        print x*y
        if x*y > 50:
            "break both loops"
Run Code Online (Sandbox Code Playgroud)

也就是说,有一个更好的方式:

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
Run Code Online (Sandbox Code Playgroud)

Mar*_*rot 654

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
Run Code Online (Sandbox Code Playgroud)

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

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
Run Code Online (Sandbox Code Playgroud)

  • 有关此问题的解释:http://psung.blogspot.com.au/2007/12/for-else-in-python.html (21认同)
  • 由于外部循环所需的continue语句,在嵌套循环不是外部for循环中的唯一代码的情况下,这通常不能很好地工作.OP示例可能过于简单. (8认同)
  • 您可以用`ok = True`替换`continue`,用`if not ok:break`替换`break`. (8认同)
  • 如果没有这些评论,那么以后的任何人都很难理解. (5认同)
  • 起初我认为`else`意味着在没有迭代时执行块.很高兴知道! (2认同)
  • @eugeney它将按预期工作。在无限序列的情况下,它将永远不会达到“继续”。如果在您的情况下使用此技术没有意义,请不要。 (2认同)
  • 关键见解:**如果内部循环没有中断,外部循环也不会.**for-else子句[仅发生](/sf/answers/698652671/)如果内部循环确实_not_打破了.然后`继续'也避免外围休息. (2认同)
  • 为这个语义重载`else` 关键字是不幸的。首先,当人们看到一个 `else:` 语句时,他们的第一个倾向是假设它是一个 if 语句的 else 块。更重要的是,它没有语法意义。如果创建者为 <loop>: 选择了类似 `andalso:` 之类的东西,并且 this-if-loop-doesn't-break 会更容易理解。哦,好吧……机会丢失了。 (2认同)

unw*_*ind 133

它至少被建议,但也被拒绝.我不认为还有另一种方法,没有重复测试或重新组织代码.有时候有点烦人.

拒绝消息中,van Rossum先生提到使用return,这是非常明智的,我需要亲自记住.:)

  • 我第二次使用`return`语句.它迫使我在第二个函数中编写内部循环,但使代码更容易理解. (12认同)
  • 当你在发电机时,范罗森先生的解决方案不起作用,这是一个相当大的洞恕我直言 (12认同)

Mr *_*ooz 64

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

def foo():
    for x in range(10):
        for y in range(10):
            print(x*y)
            if x*y > 50:
                return
foo()
Run Code Online (Sandbox Code Playgroud)

如果很难提取该函数,则可以使用内部函数,如@ 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()
    ...
Run Code Online (Sandbox Code Playgroud)

  • 在这种情况下可以只使用嵌套函数...... (2认同)
  • @ bjd2385好点,用嵌套函数更新帖子 (2认同)

Fáb*_*tos 38

使用itertools.product!

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

这是python文档中itertools.product的链接:http: //docs.python.org/library/itertools.html#itertools.product

你也可以用2个fors循环数组理解,并随时打破.

>>> [(x, y) for y in ['y1', 'y2'] for x in ['x1', 'x2']]
[
    ('x1', 'y1'), ('x2', 'y1'),
    ('x1', 'y2'), ('x2', 'y2')
]
Run Code Online (Sandbox Code Playgroud)

(格式清晰)

  • 必须做一个衬纸:>>>打印“ \ n” .join(map(str,takewhile(lambda i:i <= 50,(x * y for x,y in product(xrange(10),xrange(10 )))))) (2认同)
  • 这没有解决完全笼统地打破嵌套循环的主要问题 (2认同)
  • 这适用于简单的情况,但不适用于第二个范围依赖于第一个范围的任何情况。 (2认同)

Hal*_*ier 23

有时我使用布尔变量.天真,如果你想,但我发现阅读非常灵活和舒适.测试变量可能会避免再次测试复杂条件,也可能会收集内部循环中多个测试的结果.

    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
Run Code Online (Sandbox Code Playgroud)


dbn*_*dbn 17

如果您要引发异常,则可能会引发StopIteration异常.这至少会使意图变得明显.

  • 这是一个好主意.它不需要创建一个新的异常类,它很容易阅读. (4认同)
  • 如果你的循环是一个更大的yield结构的一部分并且你没有很好地理解这一点,这可能会产生意想不到的副作用 (2认同)

J S*_*J S 8

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