Почему «продолжать» не разрешено в предложении «наконец» в Python?
-
25-10-2019 - |
Вопрос
Следующий код повышает ошибку синтаксиса:
>>> for i in range(10):
... print i
... try:
... pass
... finally:
... continue
... print i
...
File "<stdin>", line 6
SyntaxError: 'continue' not supported inside 'finally' clause
Почему не continue
Заявление разрешено внутри finally
пункт?
PS Этот другой код, с другой стороны, не имеет проблем:
>>> for i in range(10):
... print i
... try:
... pass
... finally:
... break
...
0
Если это важно, я использую Python 2.6.6.
Решение
Использование Продолжать В наконец-то оказалось запрещено, потому что его интерпретация была бы проблематичной. Что бы вы сделали, если бы наконец-то было выполнено из-за исключения?
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
), тогда есть некоторое преимущество в том, чтобы оставить это как Ошибка синтаксиса.
Интересно, что вы можете положить возвращаться Внутри наконец-то оказалось, и это поглотит все исключения, включая Keyboardintrupt, SystemExit, а также MemoryError. Анкет Это, вероятно, тоже не очень хорошая идея ;-)
Другие советы
Ссылка на язык на питон запрещает использование continue
внутри finally
пункт. Я не совсем уверен, почему. Возможно, потому что continue
внутри try
пункт гарантирует, что finally
выполнено и решает, что continue
должен сделать в рамках finally
Пункт несколько неоднозначен.
РЕДАКТИРОВАТЬ: Комментарий @mike Christensen к вопросу указывает на ветку, в которой неоднозначность этой конструкции обсуждается разработчиками Python Core. Кроме того, за более чем девять лет использования Python я никогда не хотел этого делать, так что, вероятно, это относительно необычная ситуация, когда разработчики не хотят тратить много времени.
Продолжение заявления было незаконным в пункте, наконец, из -за проблемы с реализацией. В Python 3.8 это ограничение было снято.
Ошибка была Выпуск32489 - Разрешить «продолжить» в «наконец»..
Запрос на привлечение исправления: https://github.com/python/cpython/pull/5822
Я думаю, что причина этого на самом деле довольно проста. Оператор продолжения после того, как наконец -то ключевое слово выполняется каждый раз. Это природа окончательного утверждения. Независимо от того, бросает ли ваш код исключение, не имеет значения. Наконец будет выполнен.
Поэтому ваш код ...
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 не допускает продолжение в конце блока, потому что весь код после продолжения никогда не будет выполнен. (Sparse лучше плотного.)
Я не видел его упомянутого в другом ответе, но я думаю, что вы могли бы хотеть в этом случае 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
опять таки - В противном случае мы
continue
(а такжеi
никогда не печатается)
Возможность поднять исключение, а затем просто проглотить, потому что вы используете 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
нет?
Вы также можете рассмотреть комбинацию следующих факторов в проблеме:
finally
всегда выполняется;continue
«прерывает» текущая итерация.
Это будет означать, что внутри каждой петли, из -за finally
всегда выполнять, у вас всегда будет continue
Ведьма в основном говорит «прервать текущую итерацию», «прервать текущую итерацию», «прервать текущую итерацию» ... ведьма на самом деле не имеет никакого смысла. Но не имеет смысла ни использовать break
а также return
. Анкет Текущая итерация также прерывается с единственной разницей, что теперь вы получите только одну итерацию.
Итак, вопрос "почему continue
не допускается в finally
? »Можно также спросить как« Почему break
а также return
допустимый?".
Может, потому что это имело смысл не в тот момент? Это было решение разработчиков, и теперь оно так, как это? Конечно, это также может быть лень реализации, но кто знает, может быть, они что -то имели в виду, и, возможно, в другой версии Python было бы больше смысла иметь это по -другому?
Идея в том, что Примеры здесь просто экстремальные. Анкет Вы не просто пишете код, не так ли? Наверняка будет какая -то логика в finally
блокировать, чтобы сказать, когда break/return/continue
, что угодно, и не просто заставляют это так же тупо. Как таковой, ИМХО continue
внутри а finally
должно быть разрешено, потому что я был бы признателен за написание чистого кода с использованием continue
в finally
Если это то, что мне нужно, вместо того, чтобы прибегать к обходному пути кода для этого ограничения (т.е. в философии Python «мы все согласны с взрослыми здесь»).
Теперь эта функция доступна с выпуском 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