Pythonは、キーが存在しない場合、dictのキーを更新します


107

キーがdict.keys()にない場合、キーと値のペアをdictに挿入したいと思います。基本的に私はそれを行うことができます:

if key not in d.keys():
    d[key] = value

しかし、もっと良い方法はありますか?または、この問題のpythonicソリューションは何ですか?


回答:


149

電話する必要はないd.keys()ので

if key not in d:
    d[key] = value

十分です。より明確で読みやすい方法はありません。

dict.get()キーがすでに存在する場合は既存の値を返す、で再度更新できます。

d[key] = d.get(key, value)

しかし、私はこれに反対することを強くお勧めします。これはコードゴルフであり、メンテナンスと読みやすさを妨げます。


コードを使用するスレッドが複数ある場合、これを同期する必要がありますか?
ed 2220

1
@ ed22はい。複数のバイトコード命令で構成されており、その間でスレッドを切り替えることができます。
MartijnPieters

84

使用dict.setdefault()

>>> d = {1: 'one'}
>>> d.setdefault(1, '1')
'one'
>>> d    # d has not changed because the key already existed
{1: 'one'}
>>> d.setdefault(2, 'two')
'two'
>>> d
{1: 'one', 2: 'two'}

6
dict.setdefault()実際には、値にアクセスしようとする場合にのみ使用する必要があります。
MartijnPieters

14
@MartijnPieters:なぜそれが重要なのですか?名前setdefault()は何が起こっているかを明確に説明しています-値も返すことはそれほど重要ではなく、少し風変わりなIMOです。なぜこれが望ましくないのかについて、簡単な説明またはリンクを提供していただけますか?
mhawke 2017

6
グループ化ループのように、値が存在することを期待する式で使用しますfor obj in iterable: d.setdefault(key_for_obj(obj), []).append(obj)。返される値について奇妙なことは何もありません。それがメソッドの要点です
MartijnPieters

2
また、キーがまだ存在しない場合にのみキーを設定するという、実行しようとしていることを覆い隠します。読みやすさは重要if key not in d:です。テストを使用するだけです。
MartijnPieters

7
@MartijnPieters:説明ありがとうございます。docstringを読んだことは、setdefault()あなたが言ったことに適合しているようです。を使用するdefaultdict(list)と、例よりも読みやすいコードになります...したがって、標準の辞書を使用する必要がない限り、おそらくそれは使用できません。全体的に、if key not in dより明確です。
mhawke 2017

25

Python 3.9以降、マージ演算子 |を使用して2つの辞書をマージできます。右側の口述が優先されます。

d = { key: value } | d

注:これにより、更新された値で新しい辞書が作成されます。


6
これは興味深いことですが、受け入れられた答えよりも読みやすいとは思いません
JustinFuruness20年

2
私にとって、2つのディクテーションをマージする方法があることを知ってうれしいです
オースティン

このマージには課題があります。キーが同じである場合、マージは値を無視します。それが意図している場合、それは機能します。
Joe Ferndz3

6

以下を使用すると、複数の値を挿入でき、デフォルト値も使用できますが、新しい辞書を作成しています。

d = {**{ key: value }, **default_values}

私は最も投票された回答でそれをテストしました、そしてそれが次の例で見ることができるように平均してこれはより速いです、。

forループベースのメソッドとunpack演算子を使用したdictの理解を比較する速度テスト forループベースのメソッドとアンパック演算子メソッドを使用したdictの理解を比較する速度テスト。

d = default_vals.copy()最初のケースでコピー()が作成されない場合、桁違い10**5以上に達すると、最も投票された回答が速くなります。両方の方法のメモリフットプリントは同じです。


1
それなら、なぜそもそもそれを提案するのか
jonathan

1
この解決策は私には完全に有効に見えます。また、1つの宣言で複数の値を更新することもできます。
ロタレティ

どうもありがとうございます。しかし、そうあるべきだと思われます{**default_values, **{ key: value }}
osexp20 0320

0

上記の答えによると、setdefault()メソッドは私のために働いた。

old_attr_name = mydict.setdefault(key, attr_name)
if attr_name != old_attr_name:
    raise RuntimeError(f"Key '{key}' duplication: "
                       f"'{old_attr_name}' and '{attr_name}'.")

このソリューションは一般的ではありませんが。この特定のケースでちょうど私に合った。正確な解決策は、key最初のものをチェックすることです(すでにアドバイスされているように)がsetdefault()、辞書での余分なルックアップを1つ回避します。つまり、小さいながらもパフォーマンスが向上します。

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