Вырвавшись из вложенных циклов

голоса
179

Можно создать дубликат:
Как вырваться из нескольких циклов в Python?

Есть ли более простой способ вырваться из вложенных циклов, чем бросать исключение? (В 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
Задан 17/03/2009 в 10:24
источник пользователем
На других языках...                            


8 ответов

голоса
488
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
Ответил 17/03/2009 в 13:27
источник пользователем

голоса
102

Это по крайней мере , было предложено, но и отвергнуто . Я не думаю , что есть еще один способ, не хватает повторить тест или реорганизовать код. Это иногда немного раздражает.

В сообщении отбраковки , г - н ван Россум упоминает , используя return, которые действительно разумны и что - то мне нужно помнить лично. :)

Ответил 17/03/2009 в 10:27
источник пользователем

голоса
53

Если вы в состоянии извлечь код цикла в функцию, 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()
    ...
Ответил 17/03/2009 в 13:37
источник пользователем

голоса
29

Используйте itertools.product!

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

Вот ссылка на itertools.product в документации питона: http://docs.python.org/library/itertools.html#itertools.product

Ответил 26/10/2011 в 18:47
источник пользователем

голоса
18

Иногда я использую логическую переменную. Наивный, если вы хотите, но я считаю его достаточно гибким и удобным для чтения. Тестирование переменной может избежать тестирования снова сложных условий и может также собирать результаты нескольких тестов во внутренних петлях.

    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
Ответил 16/05/2011 в 21:50
источник пользователем

голоса
14

Если вы собираетесь вызвать исключение, вы можете поднять исключение StopIteration . Это, по крайней мере , сделать намерение очевидным.

Ответил 14/08/2012 в 01:31
источник пользователем

голоса
8

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

Ответил 17/03/2009 в 11:29
источник пользователем

голоса
3

В данном конкретном случае, вы можете объединить петлю с современным питоном (3.0 и 2.6, вероятно, тоже) с помощью itertools.product.

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

Ответил 17/03/2009 в 10:58
источник пользователем

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more