2

通常、try/except ブロックを使用して、ステートメントの 1 つが例外を引き起こすまで一連のステートメントを実行できます。

私は反対のことをしたいと思います - それらのそれぞれが例外を引き起こす可能性が高い一連のステートメントを実行しますが、そのうちの1つはそうしません。

ここにいくつかの擬似コードがあります:

try:
    c = 1 / 0       # this will cause an exception
    c = 1 / (1 - 1) # this will cause an exception
    c = int("i am not an integer") 
                    # this will cause an exception
    c = 1           # this will not cause an exception
    c = 2           # this statement should not be reached
    c = None        # this would be a final fallback in case everything exceptioned

print c         # with this code, c should print "1"

このようなものを使用したい方法は、データ解析です。ユーザーは、いくつかの異なる形式のいずれかのデータを提供する場合があります。さまざまな形式を解析しようとすると、データが形式と一致しない場合に例外が発生します。数十の異なるフォーマットが存在する可能性があります。ステートメントは優先順にリストされます。パーサーの 1 つが成功するとすぐに、それが変数に必要な結果になります。

各試行を試行/例外内にラップすると、見苦しいスパゲッティ コードが作成されます。

c = None

try:
    c = 1 / 0
except:
    pass

if (c == None):
    try:
        c = 1 / (1 - 1)
    except:
        pass

if (c == None):
    try:
        c = int("i am not an int")
    except:
        pass

... and so on

これを行うより良い方法はありますか?

4

2 に答える 2

3

私は、配列でラムダ関数を使用すると言います:

L = [ lambda : 1 / 0, 
      lambda : 1 / (1 - 1), 
      lambda : int("i am not an int"), 
      lambda : 2 ]

for l in L:
  try:
    x = l()
    break
  except:
    pass
print x

現在の例/リクエストでは、テストに入力データを必要としない/使用する必要はありませんが、最終的にはラムダを使用すると非常に簡単になります。

于 2013-05-26T07:27:29.853 に答える
1

単純に関数にするのはどうですか?私はあなたの疑似コードを使用しているので、より良い機能はなく、読みやすくなります。

def doIt():

    try:
        return 1 / 0
    except:
        pass

    try:
        return 1 / (1 - 1)
    except:
        pass

    try:
        return int("i am not an int")
    except:
        pass

c = doIt()
于 2013-05-26T07:05:11.617 に答える