PythonのEAFP原則とは何ですか?


回答:


215

用語集から:

許可より許しを求める方が簡単です。この一般的なPythonコーディングスタイルは、有効なキーまたは属性の存在を想定しており、想定が誤っていることが判明した場合は例外をキャッチします。このクリーンで速いスタイルは、多数のtryand exceptステートメントの存在によって特徴付けられます。この手法は、Cなどの他の多くの言語に共通のLBYLスタイルとは対照的です。

例としては、辞書のキーにアクセスする試みがあります。

EAFP:

try:
    x = my_dict["key"]
except KeyError:
    # handle missing key

LBYL:

if "key" in my_dict:
    x = my_dict["key"]
else:
    # handle missing key

LBYLバージョンは、辞書内のキーを2回検索する必要があり、読みにくいと見なされることもあります。


34
拡張機能は、別の利点が競合状態の回避であることです...たとえば、ファイルを開いてみて、それを取得した場合、それを取得します。代わりに、見てのあなたはそれを得ることができれば、後でそれを取得し、チェックとアクセスattempの間の時間の非常に小さい量で、あなたはもはやそれを得ることができることを実現しようとすると、その後、。
Jon Clements

23
ハンドラはちょうどにデフォルト値を代入されている場合Pythonはまた、それらの両方を回避する方法を提供しxたキーが存在しない場合:x = mydict.get('key')返されますNone場合'key'ではありませんmy_dict。また、を実行することもできます.get('key', <something>)。キーが辞書にない場合は、xに何かが割り当てられます。dict.setdefault()また、collections.defaultdict過剰なコードを回避するためにも役立ちます。
JAB

1
私は思うexcept KeyErrorだけでなく、として、AttributeError単純だが、最悪の例のいくつかです。何度もexcept AttributeError間違った場所に置かれたために何かをデバッグするのに行き詰まり、チェーンのより深いところで発生した誤った属性エラーをキャッチしてしまいました。私が思うより良い例は以下の通りですtry: open() ... except: IOError。またはtry: parseLine() ... except ParseError
スキー

4
@skiこれは少し異なる問題です。誤った例外をキャッチしないように、常に tryブロックを最小限に抑える必要あります。また、私は一般にEAFPスタイルを好みません。私はここで質問に答えているだけで、一部の人々はそれを好むと述べています。私は、ケースバイケースで、どのコードが最も読みやすく見えるかを決定します。
Sven Marnach

1
グレイスホッパーがこのフレーズの出典である可能性が高いことを言及する価値があると私は思います。彼女の引用は、「敢えてやる。許可を得るよりも許しを求める方が簡単です」(プログラミングに限定されない)。
Fabien Snauwaert、

9

別の例で説明してみます。

ここでは、ファイルにアクセスして内容をコンソールに出力しようとしています。

LBYL-飛躍する前に見て:

ファイルにアクセスできるかどうかを確認し、アクセスできる場合は、ファイルを開いて内容を印刷します。ファイルにアクセスできない場合は、そのelse部分にヒットします。これが競合状態である理由は、最初にアクセスチェックを行うためです。到達するまでに、with open(my_file) as f:いくつかのアクセス許可の問題(たとえば、別のプロセスが排他的なファイルロックを取得するなど)のためにアクセスできなくなっている可能性があります。このコードはエラーをスローする可能性が高く、ファイルにアクセスできると考えていたため、そのエラーをキャッチできません。

import os

my_file = "/path/to/my/file.txt"

# Race condition
if os.access(my_file, os.R_OK):
    with open(my_file) as f:
        print(f.read())
else:
    print("File can't be accessed")

EAFP-許可よりも許しを求める方が簡単:

この例では、ファイルを開こうとしているだけで、開けない場合はをスローしIOErrorます。可能であれば、ファイルを開いて内容を印刷します。だから私たちは何かを求めているのではなく、それをやろうとしているのです。うまくいけば、素晴らしい!そうでない場合は、エラーをキャッチして処理します。

# # No race condition
try:
    f = open(my_file)
except IOError as e:
    print("File can't be accessed")
else:
    with f:
        print(f.read())

これを競合状態として説明することが正しいかどうかはわかりません。ファイルにアクセスできるかどうか。
ds4940

3
@ ds4940ファイルのアクセス可能性が6行目と7行目の間で変更された場合、つまり、ファイルがアクセス可能かどうかを確認してから開くまでの競合状態です。
Markus von Broady、

@MarkusvonBroadyは同意し、回答を編集して競合状態の他の参加者の例を提供しました。
ds4940

6

それを「楽観的プログラミング」と呼んでいます。アイデアは、ほとんどの場合、人々は正しいことを行い、エラーは少ないはずです。したがって、最初に「正しいこと」が発生するようにコーディングし、発生しない場合はエラーをキャッチします。

私の感覚では、ユーザーが間違いを犯すことになるとしたら、それは時間の影響を受けるものでなければならないということです。ツールを正しい方法で使用する人は、迅速に処理されます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.