Именование циклов в Python - PullRequest
15 голосов
/ 07 декабря 2011

Я недавно прочитал этот вопрос , который имел решение о маркировке циклов в Java.

Мне интересно, существует ли такая система именования циклов в Python.Несколько раз я был в ситуации, когда мне нужно вырваться из внешней петли for из внутренней петли for.Обычно я решаю эту проблему, помещая внутренний цикл в функцию, которая возвращает (среди прочего) логическое значение, которое используется как условие прерывания.Но маркировка циклов для взлома кажется намного проще, и я хотел бы попробовать это, если такая функциональность существует в python

Кто-нибудь знает, если это так?

Ответы [ 4 ]

13 голосов
/ 27 мая 2013

Вот способ разбить несколько вложенных блоков с помощью диспетчера контекста:

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
11 голосов
/ 07 декабря 2011

Было предложено включить именованные циклы в python PEP3136 , однако оно было отклонено с объяснением здесь . Отказ был в основном из-за редкого числа обстоятельств, когда читаемость кода была бы улучшена путем включения этой конструкции.

9 голосов
/ 07 декабря 2011

Несмотря на то, что есть причины для включения named loop в языковую конструкцию, вы легко можете избежать этого в 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
>>> 

Я решаю эту проблему, помещая внутренний цикл в функцию, которая возвращает (среди прочего) логическое значение, которое используется как условие прерывания.

Я думаю, тебе стоит попробовать это.Это очень питонно, просто и читабельно.

1 голос
/ 07 декабря 2011

Нет.

В зависимости от того, что вы делаете, есть хороший шанс, что вы можете использовать что-то из itertools, чтобы сгладить ваши вложенные циклы for в один цикл for.

...