Pythonのif/else
ステートメントと同様に、そのtry/except/finally
ステートメントに相当するfinally
がありますか?これを単純化できるもの:
if condition1:
do stuff
clean up
Elif condition2:
do stuff
clean up
Elif condition3:
do stuff
clean up
...
...
これに:
if condition1:
do stuff
Elif condition2:
do stuff
Elif condition3:
do stuff
...
...
finally:
clean up
finally
が呼び出されるのは、条件が満たされ、その「処理」が実行された後のみです。逆に、条件が満たされていない場合、finally
コードは実行されません。
私は冒とくを吐き出すのは嫌いですが、それを説明できる最善の方法は、GOTO
につながった 'do stuff'の各ブロックの最後にfinally
ステートメントがあることです。
基本的に、else
ステートメントの反対として機能します。 else
は、他の条件が満たされていない場合にのみ実行されますが、別の条件が満たされた場合にのみ実行されます。
次のように完全に非ハック的に実行できます。
def function(x,y,z):
if condition1:
blah
Elif condition2:
blah2
else:
return False
#finally!
clean up stuff.
いくつかの点で、別の関数を使用する必要があるほど便利ではありません。ただし、とにかく長すぎる関数を作成しないことをお勧めします。ロジックを小さく読みやすい(通常は最大1ページの長さの)関数に分離すると、実行フローのテスト、文書化、および理解がはるかに簡単になります。
注意すべきことの1つは、finally
句が例外のイベントで実行されないことです。それを行うには、try:
を追加する必要があります。
あなたのロジックはこれに似ています:
cleanup = True
if condition1:
do stuff
Elif condition2:
do stuff
Elif condition3:
do stuff
....
else:
cleanup = False
if cleanup:
do the cleanup
Glyいですが、それはあなたが尋ねたものです
Mhlesterの答えには反復コードがありますが、改善されたバージョンは次のようになります。
class NoCleanUp(Exception):
pass
try:
if condition1:
do stuff
Elif condition2:
do stuff
else:
raise NoCleanUp
except NoCleanUp:
pass
else:
cleanup
別の提案。条件が事前に計算されている場合に適している可能性があります。
if condition1:
do stuff
Elif condition2:
do stuff
...
if any([condition1, condition2, ...]):
clean_up
Ifステートメントの一部として条件を評価する場合、これは苦痛になります。その場合、any
関数についてもう一度評価する必要があるためです... Pythonは私が思っているよりも賢い。
パーティーに少し遅れましたが、最近活発になっている質問をご覧ください。
通常、私はこのようなコンテキストマネージャを作成します
class CleanUp(object):
class Cancel(Exception):
pass
def __init__(self, f_cleanup):
self.f_cleanup = f_cleanup
def __enter__(self):
return self
def __exit__(self, exception_type, exception_value, traceback):
cancelled = exception_type and issubclass(exception_type, self.__class__.Cancel)
if not cancelled:
self.f_cleanup()
return not exception_type or cancelled
def cancel(self):
raise self.__class__.Cancel
そして、あなたはこのようにそれを使用することができます
def cleanup():
print "Doing Housekeeping"
with CleanUp(cleanup) as manager:
if condition1:
do stuff
Elif condition2:
do stuff
else:
manager.cancel()
このような:
from .actions import stuff1, stuff2
actions={condition1: stuff1, condition2: stuff2}
for condition in actions:
if condition:
actions[condition]()
cleanup()
break
もちろん、条件キーは一意でハッシュ可能である必要があります。これを回避するには、別のデータ構造を使用します。
これは恐ろしいですか?
for _ in range(1):
if condition1:
do stuff
break
Elif condition2:
do stuff
break
else:
finally stuff
これはどう?
class NoFinally(Exception):
pass
try:
if condition1:
do stuff
raise NoFinally
Elif condition2:
do stuff
raise NoFinally
except NoFinally:
pass
else:
finally
正直なところ、私はこれらの両方が嫌いです