Нарушение вложенных циклов
Возможный дубликат:
Как вырваться из нескольких циклов в Python?
Есть ли более простой способ вырваться из вложенных циклов, чем бросать исключение? (В Perl вы можете давать метки для каждого цикла и, по крайней мере, продолжать внешний цикл.)
for x in range(10):
for y in range(10):
print x*y
if x*y > 50:
"break both loops"
I.e., есть ли лучший способ, чем:
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
Ответы
Ответ 1
По крайней мере, было предложено, но также отклонено. Я не думаю, что есть другой способ, не повторяя тест или реорганизацию кода. Иногда это немного раздражает.
В сообщении , г-н ван Россум упоминает использование return
, что действительно разумно и что-то, что мне нужно запомнить лично.:)
Ответ 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
Ответ 3
Если вы можете извлечь код цикла в функцию, оператор 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()
...
Ответ 4
Используйте itertools.product!
from itertools import product
for x, y in product(range(10), range(10)):
#do whatever you want
break
Вот ссылка на itertools.product в документации по python:
http://docs.python.org/library/itertools.html#itertools.product
Вы также можете зациклить понимание массива с двумя форсами в нем, и разбить, когда захотите.
>>> [(x, y) for y in ['y1', 'y2'] for x in ['x1', 'x2']]
[
('x1', 'y1'), ('x2', 'y1'),
('x1', 'y2'), ('x2', 'y2')
]
(отформатировано для ясности)
Ответ 5
Иногда я использую логическую переменную. Наивный, если хочешь, но я считаю его достаточно гибким и удобным для чтения. Тестирование переменной может избежать повторного тестирования сложных условий и может также собирать результаты нескольких тестов во внутренних циклах.
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
Ответ 6
Если вы собираетесь создать исключение, вы можете создать исключение StopIteration. Это, по крайней мере, сделает очевидным намерение.
Ответ 7
Вы также можете реорганизовать свой код для использования генератора. Но это не может быть решением для всех типов вложенных циклов.
Ответ 8
В этом конкретном случае вы можете объединить циклы с современным python (3.0 и, возможно, 2.6), используя itertools.product.
Я сам взял это как правило, если вы вложили слишком много циклов (как и более, более 2), вы обычно можете извлечь одну из циклов в другой метод или объединить петли в один, как в этом случае.