if
が有効か、またはtry
をテストして例外をキャッチする必要がありますか?
たとえば、私は:
if len(my_list) >= 4:
x = my_list[3]
else:
x = 'NO_ABC'
または:
try:
x = my_list[3]
except IndexError:
x = 'NO_ABC'
いくつかの考え...
PEP 2 言います:
エラーが黙って渡されることはありません。
明示的に沈黙しない限り。
try
の代わりにif
を使用することは、エラーなしに渡されると解釈されるべきですか?もしそうなら、あなたはこのようにそれを使用することによって明示的にそれを黙らせているので、それをOKにしますか?
私はnot1つの方法しかできない状況を参照しています。例えば:
try:
import foo
except ImportError:
import baz
その結果、_try/except
_よりも_if/else
_を優先する必要があります。
多くの場合、これらは密接に関連しています。
スピードアップ
次の方法で長いリスト内の要素を見つけようとする場合:
_try:
x = my_list[index]
except IndexError:
x = 'NO_ABC'
_
tryは、index
がおそらくリストにあり、IndexErrorが通常発生しない場合に最適なオプションです。これにより、if index < len(mylist)
による追加のルックアップの必要性を回避できます。
Pythonは、あなたが扱う例外の使用を推奨しています Dive Into Python からのフレーズです。あなたの例は、例外を黙って渡すのではなく、例外を(優雅に)処理するだけでなく、例外はexceptionalインデックスが見つからない場合(したがって、Wordexception!)。
クリーナーコード
公式のPythonドキュメンテーションの言及 [〜#〜] eafp [〜#〜] :許可よりも許しを求める方が簡単ですおよび Rob Knight は、 エラーを回避するのではなくキャッチする、クリーンで読みやすいコードになります。彼の例は次のように言っています:
さらに悪い(LBYL「あなたは飛躍する前に見てください」):
_#check whether int conversion will raise an error
if not isinstance(s, str) or not s.isdigit:
return None
Elif len(s) > 10: #too many digits for int conversion
return None
else:
return int(str)
_
より良い(EAFP:許可よりも許しを求める方が簡単です):
_try:
return int(str)
except (TypeError, ValueError, OverflowError): #int conversion failed
return None
_
この特定のケースでは、まったく別のものを使用する必要があります。
x = myDict.get("ABC", "NO_ABC")
ただし、一般的には:テストが頻繁に失敗すると予想される場合は、if
を使用します。テストが単に操作を試行し、失敗した場合に例外をキャッチすることに比べてコストが高い場合は、try
を使用します。これらの条件のいずれも当てはまらない場合は、読みやすいものを選択してください。
try
ガード内ではなく、直接except
とif
を使用する場合は、競合状態の可能性がある場合はalwaysを実行する必要があります。たとえば、ディレクトリが存在することを確認する場合は、これを実行しないでください。
import os, sys
if not os.path.isdir('foo'):
try:
os.mkdir('foo')
except OSError, e
print e
sys.exit(1)
別のスレッドまたはプロセスがisdir
とmkdir
の間にディレクトリを作成する場合、終了します。代わりに、これを行います:
import os, sys, errno
try:
os.mkdir('foo')
except OSError, e
if e.errno != errno.EEXIST:
print e
sys.exit(1)
'foo'ディレクトリを作成できない場合にのみ終了します。
失敗する前に何かが失敗するかどうかを確認するのが簡単な場合は、おそらくそれを支持すべきです。結局、例外(それらに関連するトレースバックを含む)の構築には時間がかかります。
例外は次の場合に使用する必要があります。
break
で十分でない場合)、または...多くの場合、実際の答えは「どちらでもない」ことに注意してください。たとえば、最初の例では、実際にshouldを行うのは.get()
を使用してデフォルトを提供するだけです。
x = myDict.get('ABC', 'NO_ABC')
他の投稿が言及するように、それは状況に依存します。特に大規模なプロジェクトでデータを使用する場合、事前にデータの有効性を確認する代わりにtry/exceptを使用すると、いくつかの危険があります。
たとえば、あなたが持っていたと仮定します:
try:
x = my_list[index_list[3]]
except IndexError:
x = 'NO_ABC'
IndexErrorは、index_listまたはmy_listの要素を取得しようとしたときに発生したかどうかについては何も言いません。
Ifの代わりにtryを使用することは、エラーをサイレントに渡すと解釈されるべきですか?もしそうなら、あなたはこのようにそれを使用することによって明示的にそれを黙らせているので、それをOKにしますか?
try
を使用することは、エラーが通過する可能性があることを認めることです。 except
を使用すると、まったくパスしません。
try: except:
ロジックがより複雑な場合は、if: else:
を使用することをお勧めします。単純なものは複雑なものよりも優れています。複雑は複雑よりも優れています。そして、許可よりも許しを求める方が簡単です。
「エラーが黙って渡されるべきではない」とは、コードがあなたが知っている例外を発生させる可能性があり、設計が可能性を認めているが、例外に対処する方法で設計していない場合です。私の見解では、明示的にエラーを黙らせることは、pass
ブロック内でexcept
のようなことをすることです。これは、「何もしない」ことが本当に正しいエラー処理であるという理解の下でのみ行われるべきです特定の状況。 (これは、よく書かれたコードのコメントがおそらく本当に必要だと思う数少ない時間の1つです。)
ただし、特定の例では、どちらも適切ではありません。
x = myDict.get('ABC', 'NO_ABC')
誰もがこれを指摘している理由-一般的に理解したいという願望と、より良い例を思い付かないことを認めたとしても-同等のサイドステップが実際に非常に多くの場合に存在し、それらを探すことが問題解決の最初のステップ。
制御フローに_try/except
_を使用するときは常に、次のことを自問してください。
try
ブロックが成功したときと失敗したときを確認するのは簡単ですか?try
ブロック内のall副作用を知っていますか?try
ブロックが例外をスローするallケースを知っていますか?try
ブロックの実装が変更されても、制御フローは期待どおりに動作しますか?これらの質問の1つ以上に対する答えが「いいえ」である場合、多くの許しが求められる可能性があります。おそらくあなたの将来の自己から。
例。私は最近、次のような大きなプロジェクトでコードを見ました:
_try:
y = foo(x)
except ProgrammingError:
y = bar(x)
_
プログラマーと話すと、意図した制御フローは次のようになりました。
Xが整数の場合、y = foo(x)を実行します。
Xが整数のリストの場合、y = bar(x)を実行します。
これは、foo
がデータベースクエリを作成し、x
が整数の場合にクエリが成功し、ProgrammingError
がリストの場合にx
をスローするため、機能しました。
ここで_try/except
_を使用するのは悪い選択です。
ProgrammingError
は、実際の問題(x
は整数ではない)を与えないため、何が起こっているのかがわかりにくくなります。ProgrammingError
は、データベース呼び出し中に発生し、時間を無駄にします。 foo
が例外をスローする前、または他のシステムの状態を変更する前にデータベースに何かを書き込むことが判明した場合、事態は本当に恐ろしくなります。ProgrammingError
が整数のリストである場合にのみx
が発生するかどうかは不明です。たとえば、foo
のデータベースクエリにタイプミスがあるとします。これにより、ProgrammingError
も発生する場合があります。その結果、x
が整数のときにbar(x)
も呼び出されるようになりました。これにより、不可解な例外が発生したり、予期しない結果が生じる可能性があります。try/except
_ブロックは、foo
の将来のすべての実装に要件を追加します。 foo
を変更するときはいつでも、リストの処理方法を考え、ProgrammingError
をスローするか、AttributeError
をスローするか、エラーをまったく発生させないようにする必要があります。一般的な意味については、 Pythonのイディオムとアンチイディオム:例外 を読むことを検討してください。
特定のケースでは、他の人が述べたように、 dict.get()
を使用する必要があります。
get(key [、default])
Keyが辞書にある場合はkeyの値を返し、そうでない場合はデフォルトを返します。デフォルトが指定されていない場合は、デフォルトでNoneに設定されるため、このメソッドはKeyErrorを発生させません。