イディオムと読みやすさについて質問がありますが、この特定のケースではPython哲学の衝突:
辞書Bから辞書Aを作成します。特定のキーがBに存在しない場合は、何もせずに続行します。
どちらの方法が良いですか?
try:
A["blah"] = B["blah"]
except KeyError:
pass
または
if "blah" in B:
A["blah"] = B["blah"]
「許しを求めて」対「単純さと明確さ」。
どちらが良いですか?
例外は条件付きではありません。
条件付きバージョンはより明確です。それは当然です。これは単純なフロー制御であり、例外ではなく条件式が設計されています。
例外バージョンは、主にループでこれらのルックアップを行うときの最適化として使用されます。一部のアルゴリズムでは、内部ループからテストを削除できます。ここにはその利点はありません。 "blah"
を2回言う必要がないという小さな利点がありますが、これらの多くを行う場合は、おそらくヘルパーmove_key
関数が必要です。
一般的に、特別な理由がない限り、デフォルトで条件付きバージョンを使用することを強くお勧めします。条件はこれを行うための明らかな方法であり、通常、あるソリューションを別のソリューションよりも優先することを強くお勧めします。
例外とダブルルックアップの両方を回避する3番目の方法もあります。これは、ルックアップが高価な場合に重要になる可能性があります。
_value = B.get("blah", None)
if value is None:
A["blah"] = value
_
辞書にNone
値が含まれると予想される場合は、NotImplemented
、Ellipsis
などの難解な定数を使用するか、新しい定数を作成できます。
_MyConst = object()
def update_key(A, B, key):
value = B.get(key, MyConst)
if value is not MyConst:
A[key] = value
_
とにかく、update()
を使用することが私にとって最も読みやすいオプションです:
_a.update((k, b[k]) for k in ("foo", "bar", "blah") if k in b)
_
私が理解していることから、dict Bからのキーと値のペアでdict Aを更新したい
update
がより良い選択です。
A.update(B)
例:
>>> A = {'a':1, 'b': 2, 'c':3}
>>> B = {'d': 2, 'b':5, 'c': 4}
>>> A.update(B)
>>> A
{'a': 1, 'c': 4, 'b': 5, 'd': 2}
>>>
Pythonパフォーマンスwikiからの直接引用:
初めて例外を除き、Wordが表示されるたびにifステートメントのテストが失敗します。多数の単語をカウントしている場合、多くの単語がおそらく複数回出現します。値の初期化が1回だけ発生し、その値の増加が何度も発生する状況では、tryステートメントを使用する方が安価です。
したがって、状況に応じて両方のオプションが実行可能であるようです。詳細については、次のリンクをご覧ください。 Try-except-performance
ここでの一般的なルールはA["blah"]
は通常存在します。そうであれば、try-exceptが適切でない場合は、if "blah" in b:
「トライ」は時間的には安いと思いますが、「除外」はもっと高価です。
2番目の例は、このコードが理にかなっていない場合に使用すべきものだと思います。
try:
A["foo"] = B["foo"]
A["bar"] = B["bar"]
A["baz"] = B["baz"]
except KeyError:
pass
B
にないキーがあるとすぐにコードが中断することに注意してください。このコードが理にかなっている場合は、例外メソッドを使用する必要があります。そうでない場合は、テストメソッドを使用します。私の意見では、より短く、意図を明確に表現しているため、例外メソッドよりも読みやすくなっています。
もちろん、update
を使用するように言っている人は正しいです。辞書の内包表記をサポートするPythonのバージョンを使用している場合、このコードを強くお勧めします。
updateset = {'foo', 'bar', 'baz'}
A.update({k: B[k] for k in updateset if k in B})
他の言語のルールは、例外的な条件、つまり通常の使用では発生しないエラーの例外を予約することです。 StopIterationはその規則によって存在すべきではないので、その規則がPythonにどのように適用されるのかわかりません。
個人的には、2番目の方法に傾いています(ただし、has_key
):
if B.has_key("blah"):
A["blah"] = B["blah"]
このように、各割り当て操作は2行(try/exceptを使用した4行ではなく)であり、スローされる例外は実際のエラーまたは見落としたものになります(存在しないキーにアクセスしようとするのではなく) 。
判明したように(質問のコメントを参照)、has_key
は非推奨です。したがって、
if "blah" in B:
A["blah"] = B["blah"]
_Python 3.8
_を開始し、 代入式(PEP 572) (_:=
_演算子)を導入すると、変数value
の条件値dictB.get('hello', None)
を順番にキャプチャできます(dict.get('hello', None)
が関連する値またはNone
を返すため)None
ではないかどうかを確認し、条件の本文内で使用します。
_# dictB = {'hello': 5, 'world': 42}
# dictA = {}
if value := dictB.get('hello', None):
dictA["hello"] = value
# dictA is now {'hello': 5}
_
なぜこれをしないのですか:
def try_except(x,col):
try:
return x[col]
except:
return None
list(map(lambda x: try_except(x,'blah'),A))