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
)、それからこれを残すことにはいくつかの利点があります 構文エラー.
興味深いことに、aを置くことができます 戻る 最終的な条件の中で、それは keyboardinterrupt, SystemExit, 、 と メモリエラー. 。それはおそらく良い考えでもありません;-)
他のヒント
Python言語リファレンス の使用を禁止します continue
以内 finally
句。理由は完全にはわかりません。おそらく continue
以内 try
節は、を保証します finally
実行され、何を決定します continue
内で行う必要があります finally
節はやや曖昧です。
編集:@Mike Christensenの質問に対するコメントは、この構造の曖昧さがPython Core開発者によって議論されているスレッドを指摘しています。さらに、Pythonの9年以上の使用で、私はこれをやりたくなかったので、開発者が時間を費やしたくないと感じるのは、おそらく比較的珍しい状況です。
継続的な声明は、実装の問題のために最終条項で違法でした。 Python 3.8では、この制限が解除されました。
バグはそうでした Issue32489-「最後に」句で「続行」を許可する.
この理由は実際には非常に簡単だと思います。最終的なキーワードが毎回実行された後の続行ステートメント。それが最終的な声明の性質です。コードが例外をスローするかどうかは無関係です。最後に実行されます。
したがって、あなたのコード...
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は、続行後のすべてのコードが実行されないため、最終的なブロックでの継続を許可しません。 (スパースは濃いよりも優れています。)
私はそれが別の応答で言及されているのを見ませんでしたが、この場合にあなたが望むかもしれないものは 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
. 。また、現在の反復は、1つの反復だけで終わる唯一の違いで中止されています。
だから、「なぜそうなのか」という質問 continue
で許可されていません finally
?」とも尋ねることができます」 break
と return
許可された?"。
たぶん、その時点では理にかなっていたからでしょうか? それは開発者の決定でした、そして今のようですか? 確かに、それは実装者の怠lazであるかもしれませんが、誰が知っているでしょう、おそらく彼らは何かを念頭に置いていたのです。おそらく、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