Подтвердить что ты не робот

Python: переход к следующей итерации во внешнем цикле

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

for ii in range(200):
    for jj in range(200, 400):
        ...block0...
        if something:
            continue
    ...block1...

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

4b9b3361

Ответ 1

for i in ...:
    for j in ...:
        for k in ...:
            if something:
                # continue loop i

В общем случае, когда у вас несколько уровней цикла и break не работает для вас (потому что вы хотите продолжить одну из верхних петель, а не одну, расположенную над текущей), вы можете сделать одно из следующих

Рефакторинг петель, которые вы хотите вывести из функции

def inner():
    for j in ...:
        for k in ...:
            if something:
                return


for i in ...:
    inner()

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

Или вы можете определить inner как вложенную функцию и позволить ей просто захватить то, что ему нужно (может быть медленнее?)

for i in ...:
    def inner():
        for j in ...:
            for k in ...:
                if something:
                    return
    inner()

Использовать исключения

Философски, это то, за что нужны исключения, прерывая поток программы через структурные блоки построения структуры (если, для, while), когда это необходимо.

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

Плохая вещь с таким подходом заключается в том, что авторы интерпретатора/компилятора обычно предполагают, что исключения являются исключительными и оптимизируются для них соответственно.

class ContinueI(Exception):
    pass


continue_i = ContinueI()

for i in ...:
    try:
        for j in ...:
            for k in ...:
                if something:
                    raise continue_i
    except ContinueI:
        continue

Создайте для этого специальный класс исключений, чтобы вы случайно не замалчивали какое-либо другое исключение.

Что-то еще полностью

Я уверен, что есть еще другие решения.

Ответ 2

for ii in range(200):
    for jj in range(200, 400):
        ...block0...
        if something:
            break
    else:
        ...block1...

Break разрушит внутренний цикл, а block1 не будет выполнен (он будет работать только в том случае, если внутренний цикл завершен нормально).

Ответ 3

В других языках вы можете пометить цикл и перерыв в помеченном цикле. Предложение Python Enhancement (PEP) 3136 предложило добавить их в Python, но Гвидо отклонил это:

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

  • Сложность, добавленная к языку, постоянно. Это не влияет на только все реализации Python, но также и каждый инструмент анализа источников, плюс, конечно, вся документация для языка.

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

Итак, если вы надеялись, что вам не повезло, посмотрите на один из других ответов, поскольку есть хорошие варианты.

Ответ 4

Я думаю, вы могли бы сделать что-то вроде этого:

for ii in range(200):
    restart = False
    for jj in range(200, 400):
        ...block0...
        if something:
            restart = True
            break
    if restart:
        continue
    ...block1...

Ответ 5

Другим способом решения этой проблемы является использование Exception().

for ii in range(200):
    try:
        for jj in range(200, 400):
            ...block0...
            if something:
                raise Exception()
    except Exception:
        continue
    ...block1...

Например:

for n in range(1,4):
    for m in range(1,4):
        print n,'-',m

результат:

    1-1
    1-2
    1-3
    2-1
    2-2
    2-3
    3-1
    3-2
    3-3

Предполагая, что мы хотим перейти к внешнему n циклу из m loop, если m = 3:

for n in range(1,4):
    try:
        for m in range(1,4):
            if m == 3:
                raise Exception()            
            print n,'-',m
    except Exception:
        continue

результат:

    1-1
    1-2
    2-1
    2-2
    3-1
    3-2

Ссылка ссылки: http://www.programming-idioms.org/idiom/42/continue-outer-loop/1264/python

Ответ 6

Мы хотим найти что-то, а затем остановить внутреннюю итерацию. Я использую систему флагов.

for l in f:
    flag = True
    for e in r:
        if flag==False:continue
        if somecondition:
            do_something()
            flag=False