сломать и продолжить работу

def funcA(i):
   if i%3==0:
      print "Oh! No!",
      print i
      break

for i in range(100):
   funcA(i)
   print "Pass",
   print i

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


person ThunderEX    schedule 21.12.2012    source источник


Ответы (4)


Функция не может прерывать или продолжать код, из которого она вызывается. Разрыв/продолжение должен появляться буквально внутри цикла. Ваши варианты:

  1. вернуть значение из funcA и использовать его, чтобы решить, прерывать ли
  2. вызвать исключение в funcA и перехватить его в вызывающем коде (или где-то выше по цепочке вызовов)
  3. напишите генератор, который инкапсулирует логику разрыва, и перебирайте его вместо range

Под № 3 я имею в виду что-то вроде этого:

def gen(base):
    for item in base:
        if item%3 == 0:
           break
        yield i

for i in gen(range(1, 100)):
    print "Pass," i

Это позволяет вам поставить разрыв с условием, сгруппировав их в генератор на основе «базового» итератора (в данном случае диапазона). Затем вы выполняете итерацию по этому генератору вместо самого диапазона, и вы получаете прерывающее поведение.

person BrenBarn    schedule 21.12.2012
comment
генератор, который инкапсулирует логику прерывания? - person ThunderEX; 21.12.2012
comment
@ThunderEX - что-то вроде itertools.takewhile наверное - person eumiro; 21.12.2012
comment
@ThunderEX: Да, похоже на takewhile. Смотрите мой отредактированный ответ. - person BrenBarn; 21.12.2012

Уточняющий ответ БренБарнса: break к счастью не будет распространяться. break - разорвать текущий цикл, и точка. Если вы хотите распространить событие, вам следует raise создать исключение. Хотя создание исключения для разрыва цикла — это действительно уродливый способ разорвать циклы и хороший способ сломать ваш код.

ПОЦЕЛУЙ! Проще всего было бы проверить условие прямо в цикле

def my_condition(x):
  return x == 4

for i in xrange(100):
  if my_condition(i): break
  print i

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

# exception example
for i in xrange(100):
  if i == 4: raise Exception("Die!")
  print i

Как уже упоминалось, это действительно уродливый дизайн. Представьте, что вы забыли перехватить это исключение, или изменили его тип с Exception на MyBreakException и забыли изменить его где-то в try/except верхней части кода...

Пример генератора имеет свои достоинства, он делает ваш код более функциональным стилем (который я лично обожаю)

# generator example
def conditional_generator(n, condition):
  for i in xrange(n):
    if condition(i):
      break
    else:
      yield i


for i in conditional_generator( 100, my_condition ):
  print i

...который похож на takewhile, упомянутый Эумиро

person Jakub M.    schedule 21.12.2012

Break не будет распространяться между функциями, вам нужно поместить его где-нибудь прямо в цикл.

person LtWorf    schedule 21.12.2012

person    schedule
comment
Не могли бы вы добавить объяснение того, как этот код отвечает на вопрос? - person Fund Monica's Lawsuit; 18.05.2016