2010-07-28 2 views
24
for row in b: 
    for drug in drug_input: 
     for brand in brand_names[drug]: 

из третьего цикла, как мне выйти из текущего цикла и перейти к следующему значению for row in b:?python: выход из двух петель

+0

Я бы, наверное, обернул этот блок в попытке и вырвался из него рейзом. –

+0

, пожалуйста, покажите мне, как –

+0

Могу ли я спросить, какое условие во внутреннем цикле заставит «перерыв»? –

ответ

22

Это один использует логическое значение, чтобы увидеть, если вы сделали еще:

done = False 
for x in xs: 
    for y in ys: 
     if bad: 
      done = True 
      break 

    if done: 
     break 

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

for x in xs: 
    for y in ys: 
     if bad: 
      break 
    else: 
     continue 

    break 
+0

Ну, у него было три петли, а не два. –

+1

Ну, я подумал, что, возможно, OP сможет экстраполировать до трех циклов. –

+2

@Teodor: прочитайте q. тщательно - крайняя петля не должна быть выведена, поэтому пример w/2 петель - это правильная вещь –

2

Непроверенные:

inner_termination=False 
for row in b: 
    for drug in drug_input: 
     for brand in brand_names[drug]: 
      <blah> 
      if break_condition: 
       inner_termination=True 
       break 
      <blah> 
     if inner_termination: 
      inner_termination=False 
      break 
7
for row in b: 
    more_drugs = True 
    for drug in drug_input: 
     for brand in brand_names[drug]: 
      if something: 
       more_drugs = False 
       break 

     if not more_drugs: 
      break 

Python не имеют структуру управления для разрушения из двух петель сразу, так что вам нужно сделать что-то руководство, как это.

+0

@cjrh: Мне любопытно: почему бы вам написать «Великий ответ «но не проголосовать за ответ? Нет давления ... –

+1

Вы видели мой ответ? –

+0

А теперь я понял! :) –

6

Если у вас есть три уровня цикла в одном методе, вам, вероятно, нужно переосмыслить свой дизайн.

  • Разделите свой метод на более мелкие, более простые методы.
  • Используйте список понимания и методы, такие как all и any, чтобы избежать написания явных циклов.

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

+1

Я не уверен, что согласен с этим, особенно в случае итерации над сложной структурой данных. Иногда у вас есть словари в словарях в словарях! – katrielalex

+0

@karielalex: Вы не согласны с обоими пунктами или просто с секундой? –

+0

С «Если у вас три уровня цикла в одном методе, вам, вероятно, нужно переосмыслить свой дизайн». Я думаю, что существует разница между случаем итерации по структуре данных - в этом случае множественная итерация семантически одна секция и ее не нужно разделять или обрезать - и случай, когда слишком много делается в одном месте , В последней ситуации я согласен с обоими вашими пунктами. Например, я недавно построил DFA, который имел таблицу перехода «начальный узел» -> 'arc type' ->' guard' -> 'final node'. Для итерации по всем краям вам нужны три петли! – katrielalex

2
for row in b: 
    ok = True 
    for drug in drug_input: 
     if not ok: 
      break; 
     for brand in brand_names[drug]: 
      if not ok: 
       break 
      if whatever: 
       ok = False 
2

try/except/raise, как это было предложено в комментарии @ gddc, является одним из возможных вариантов. Еще один является «обернуть» два вложенных цикла в одно:

for row in b: 
    for brand in (b for d in drug_input for b in brand_names[d]): 
    ... 

Теперь, breakfor brand из вложенного цикла будет вернуться к уровню for row внешнего контура. Конечно, это работает только тогда, когда код, который здесь заменен на ..., не обязательно должен содержать имя drug, связанное с исследуемым препаратом. Это дело для вас?

+0

Достаточно просто, чтобы получить название лекарственного средства требуется. 'для бренда, наркотиков в ((b, d) для d в drug_input для b в brand_names [d]):' –

4

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

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

6

обработки исключений биения настройки переменных повсюду IMO

for row in b: 
    for drug in drug_input: 
     try: 
      for brand in brand_names[drug]: 
       if some_condition: 
        raise StopIteration 
     except StopIteration: 
      break 
+0

Исключения только для исключительных ситуаций! –

+1

«Это происходит от Exception, а не от StandardError, так как это не считается ошибкой в ​​его обычном приложении». http://docs.python.org/library/exceptions.html#exceptions.StopIteration – brianz

+1

Хорошо, это было довольно хорошее возвращение :) Но если серьезно, не обрабатывайте исключения для потока управления. На любом языке. Обработчик try-except - очень, очень распространенный визуальный сигнал для «чего-то необычного». –

4

Последние PEP Я вижу, запрашивающие эту функцию в 3136 (и было отвергнуто): http://mail.python.org/pipermail/python-3000/2007-July/008663.html

Ближайшей & чистейшей вещи, которую я мог видеть того, что вы хотите сделать следующее: (а так как даже названия типов ограничены, вы можете объявить LocalBreak в пределах необходимой функции):

class LocalBreak(Exception): pass 

try: 
    for i in ...: 
     for h in ...: 
      for j in ...: 
       if should_break(j): 
       raise LocalBreak() 
except LocalBreak: 
    pass 
2
for a in aa: 
    for b in bb: 
     for c in cc: 
      if c == a[b]: 
       break 
     else: 
      continue 
     break 

Python поддерживает for...else заявления. else блок оценивается, если внутренний break не запускается.

+1

Извините, не могли бы вы рассказать мне, что это добавляет к текущему контенту? –

2

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

def example(self, drug_input): 
    ok = False 
    for x in drug_input["names"]: 
     for y in range(drug_input["number_of_drugs"]): 
      for z in drug_input["list_of_drugs"]: 
       # do stuff 
       if ok: 
        return drug_costs 

Теперь, возможно, переформулировать ваша логика, как это сложно, но я уверен, рефакторинга поможет другим способом.

Смежные вопросы