web-dev-qa-db-ja.com

PythonのIf / Elifステートメントの「最終的に」同等

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は、他の条件が満たされていない場合にのみ実行されますが、別の条件が満たされた場合にのみ実行されます。

21
nobillygreen

次のように完全に非ハック的に実行できます。

def function(x,y,z):
    if condition1:
        blah
    Elif condition2:
        blah2
    else:
        return False

    #finally!
    clean up stuff.

いくつかの点で、別の関数を使用する必要があるほど便利ではありません。ただし、とにかく長すぎる関数を作成しないことをお勧めします。ロジックを小さく読みやすい(通常は最大1ページの長さの)関数に分離すると、実行フローのテスト、文書化、および理解がはるかに簡単になります。

注意すべきことの1つは、finally句が例外のイベントで実行されないことです。それを行うには、try:を追加する必要があります。

12
Daniel Fairhead

あなたのロジックはこれに似ています:

cleanup = True
if condition1:
    do stuff
Elif condition2:
    do stuff
Elif condition3:
    do stuff
....
else:
    cleanup = False

if cleanup:
    do the cleanup

Glyいですが、それはあなたが尋ねたものです

3

Mhlesterの答えには反復コードがありますが、改善されたバージョンは次のようになります。

class NoCleanUp(Exception):
    pass

try:
    if condition1:
        do stuff
    Elif condition2:
        do stuff
    else:
        raise NoCleanUp
except NoCleanUp:
    pass
else:
    cleanup
2
JLT

別の提案。条件が事前に計算されている場合に適している可能性があります。

if condition1:
    do stuff
Elif condition2:
    do stuff
...
if any([condition1, condition2, ...]):
    clean_up

Ifステートメントの一部として条件を評価する場合、これは苦痛になります。その場合、any関数についてもう一度評価する必要があるためです... Pythonは私が思っているよりも賢い。

1
Pig

パーティーに少し遅れましたが、最近活発になっている質問をご覧ください。

通常、私はこのようなコンテキストマネージャを作成します

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()
1
Claus Nielsen

このような:

from .actions import stuff1, stuff2

actions={condition1: stuff1, condition2: stuff2}
for condition in actions:
    if condition:
        actions[condition]()
        cleanup()
        break

もちろん、条件キーは一意でハッシュ可能である必要があります。これを回避するには、別のデータ構造を使用します。

0
DylanYoung

これは恐ろしいですか?

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

正直なところ、私はこれらの両方が嫌いです

0
mhlester