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

Почему `continue` не разрешено в` finally` в Python?

Следующий код вызывает синтаксическую ошибку:

>>> for i in range(10):
...     print i
...     try:
...        pass
...     finally:
...        continue
...     print i
...
  File "<stdin>", line 6
SyntaxError: 'continue' not supported inside 'finally' clause

Почему в предложении finally разрешен оператор continue?

P.S. Этот другой код, с другой стороны, не имеет проблем:

>>> for i in range(10):
...     print i
...     try:
...        pass
...     finally:
...        break
...
0

Если это имеет значение, я использую Python 2.6.6.

4b9b3361

Ответ 1

Использование продолжения в окончательной статье запрещено, поскольку ее интерпретация была бы проблематичной. Что бы вы сделали, если finally-предложение выполнялось из-за исключения?

for i in range(10):
    print i
    try:
       raise RuntimeError
    finally:
       continue        # if the loop continues, what would happen to the exception?
    print i

Мы можем принять решение о том, что должен делать этот код, возможно, проглатывая исключение; но хороший дизайн языка предполагает иное. Если код смущает читателей или если есть более ясный способ выразить предполагаемую логику (возможно, с помощью try: ... except Exception: pass; continue), то есть некоторое преимущество оставить это как SyntaxError.

Интересно, что вы можете поместить возврат внутри finally-предложения, и он проглотит все исключения, включая KeyboardInterrupt, SystemExit и MemoryError. Это, вероятно, тоже не очень хорошая идея: -)

Ответ 2

Справочник по языку Python запрещает использование continue в предложении finally. Я не совсем понимаю, почему. Возможно, потому что continue в предложении try гарантирует выполнение finally и решение о том, что continue должно делать в предложении finally, несколько неоднозначно.

Изменить: комментарий @Mike Christensen на вопрос указывает на поток, где эта неоднозначность конструкции обсуждается разработчиками ядра Python. Кроме того, в течение более чем девяти лет использования Python я никогда не хотел этого делать, поэтому, вероятно, это относительно необычная ситуация, когда разработчикам не хочется тратить много времени.

Ответ 3

Я думаю, что причина этого на самом деле довольно проста. Оператор continue после ключевого слова finally выполняется каждый раз. Таков характер заявления окончательного утверждения. Независимо от того, делает ли ваш код исключение, не имеет значения. Наконец, будет выполнен.

Поэтому ваш код...

for i in range(10):
   print i
   try:
       pass
   finally:
       continue
   print i # this (and anything else below the continue) won't ever be executed!

эквивалентен этому коду...

for i in range(10:
    print i
    try:
        pass
    finally:
        pass

который является более чистым и терпким. Python не разрешает продолжить в блоке finally, потому что весь код после продолжения никогда не будет выполнен. (Рельеф лучше плотного.)

Ответ 4

Я не видел, чтобы это упоминалось в другом ответе, но я думаю, что в этом случае вам может понадобиться try..else:

for i in range(10):
    print i
    try:
       #pass <= I commented this out!
       do_something_that_might_fail(i)
    except SomeException:
       pass
    else:
       continue
    print i

Блок else выполняется только в случае отсутствия исключения. Итак, что это значит:

  • Мы print i
  • Мы try до do_something_that_might_fail(i)
  • Если он выбрасывает SomeException, проваливается и print i снова
  • В противном случае мы continuei никогда не печатаем)

Ответ 5

Возможность получить исключение, а затем просто усвоить, потому что вы используете continue, является сильным аргументом, но исключение также проглатывается, если вместо этого использовать break или return.

Например, это работает, и исключение проглатывается:

for i in range(10):
    print i
    try:
        raise Exception
    finally:
        break
    print i       # not gonna happen

Это снова работает без ошибок (когда в функции), и исключение также проглатывается:

for i in range(10):
    print i
    try:
        raise Exception
    finally:
        return
    print i       # not gonna happen

Итак, почему допустимы break и return в блоке finally с или без возможных поднятых ошибок, но continue not?

Вы также можете рассмотреть комбинацию следующих факторов в проблеме:

  • finally всегда выполняется;
  • continue "прерывает" текущую итерацию.

Это будет означать, что внутри каждого цикла из-за того, что finally всегда выполняется, у вас всегда будет continue ведьма в принципе говорит "прерывать текущую итерацию" , "прерывать текущую итерацию" , "прерывать текущую итерацию" ... ведьма на самом деле не имеет никакого смысла. Но не имеет смысла использовать break и return. Текущая итерация также прерывается с единственной разницей что теперь у вас есть только одна итерация.

Итак, вопрос "Почему continue не разрешено в finally?"? также можно задать как "Почему break и return разрешено?".

Может быть, потому что это имело смысл не в тот момент? Это было решение разработчиков, и теперь это похоже на это. Конечно, это может быть и ленивость разработчика, но кто знает, может быть, они что-то имели в виду и, возможно, в другой версии Python, это сделало бы больше смысл иметь это по-другому?

Идея состоит в том, что примеры здесь просто экстремальные. Вы не просто пишете такой код, не так ли? Конечно, есть некоторые логики в блоке finally, чтобы сказать, когда break/return/continue, что угодно, и не просто так тупо. Таким образом, IMHO continue внутри a finally должно быть разрешено, потому что я хотел бы написать чистый код с использованием continue в finally, если это то, что мне нужно, вместо того, чтобы прибегать к обходному пути кода для этого ограничения (т.е. в философии Python "Мы все соглашаем взрослых здесь" ).

Ответ 7

Теперь эта функция доступна с версии 3.8

https://docs.python.org/3/whatsnew/3.8.html

Пример кода

def new_f():
    for i in range(0,24):
        try:
            print(1/0)
        except:
            print('In Exception')
        finally:
            print('In finally')
            continue