在Python中给循环命名

29

我最近阅读了这个问题,其中有一个关于在Java中标记循环的解决方案。

我想知道是否存在这样的循环命名系统可以在Python中使用。我多次遇到这种情况,需要从内部for循环中跳出外部for循环。通常,我通过将内部循环放入返回布尔值(以及其他内容)的函数中来解决此问题,该布尔值用作跳出条件。但是,为了跳出循环而标记循环似乎更简单,如果Python中存在这样的功能,我想尝试一下。

有人知道它是否存在吗?


请查看第二个答案,希望能对您有所帮助。但据我所知,目前并不存在这样的系统。 - John Doe
但是为了中断循环而标记循环似乎要简单得多?比正确的函数还简单?为什么?你能提供一些证据来说明这将会更“简单”吗? - S.Lott
2
我手头没有例子,但是有这样一种情况,我需要创建一个仅在那个位置使用的函数。也许“更简单”这个词不太准确。我的意思是,我不必为了在那个位置使用而定义一个新函数。 - inspectorG4dget
嵌套函数定义有什么问题?此外,重新设计内部循环以避免使用break怎么样? - S.Lott
2
我只是不喜欢它们。我想这是个人偏好。 - inspectorG4dget
4个回答

21

以下是使用上下文管理器来打破多个嵌套块的一种方法:

import contextlib

@contextlib.contextmanager
def escapable():
    class Escape(RuntimeError): pass
    class Unblock(object):
        def escape(self):
            raise Escape()

    try:
        yield Unblock()
    except Escape:
        pass

您可以使用它来跳出多个循环:
with escapable() as a:
    for i in xrange(30):
        for j in xrange(30):
            if i * j > 6:
                a.escape()

甚至可以嵌套使用:

with escapable() as a:
    for i in xrange(30):
        with escapable() as b:
            for j in xrange(30):
                if i * j == 12:
                    b.escape()  # Break partway out
                if i * j == 40:
                    a.escape()  # Break all the way out

4
是的,与仅仅使用break 2 (php)或者continue loop1;(javascript)相比,这样做确实更易读。此外,这个充斥着缩进问题的代码真的很符合Python风格吗?使用raise StopIteration似乎是最干净、最易读、最符合Python风格的解决方案。 - Stof

20

有一个提案要在Python中引入命名循环PEP3136,但是,它被拒绝了,并附有解释here。 拒绝主要是因为在包含此结构的情况下可以提高代码可读性的情况非常罕见。


标记循环经常被用作其他语言中“goto”的替代品。Python没有goto,但有几种替代方案 - undefined

15

虽然在语言结构中包含命名循环的原因是存在的,但你可以在Python中轻松避免使用它而不影响可读性。 一个在Python中实现的相关示例:

>>> try:
    for i in xrange(0,5):
        for j in xrange(0,6):
            if i*j > 6:
                print "Breaking"
                raise StopIteration
            print i," ",j
except StopIteration:
    print "Done"


0   0
0   1
0   2
0   3
0   4
0   5
1   0
1   1
1   2
1   3
1   4
1   5
2   0
2   1
2   2
2   3
Breaking
Done
>>> 

我通过将内部循环放入一个函数中解决了这个问题,该函数返回(其中包括)一个布尔值作为跳出条件。

我认为你应该尝试这种方法。这非常符合Python语言的风格,简单易读。


3
在Python中使用异常来控制流程是完全可行的,尽管在其他语言中通常被认为是不好的风格,原因是性能问题。 - kindall
4
如果我只想“继续”外层循环,而不是停止它怎么办? - Guillochon
2
@Guillochon 只需将try语句放在第一个for循环内部即可。 - Dylanthepiguy

1

不行。

根据您正在做的事情,使用itertools中的某些内容将嵌套的for循环展开为单个for循环的可能性很大。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接