やりたいこと
- 複数の辞書を結合して1つの辞書にしたい
- ついでに他にも要素を追加したい
dictA = {'A1': 1, 'A2': 1}
dictB = {'B1': 1, 'B2': 1}
# ---(辞書の結合 & 要素の追加)---
# => {'key1': 1, 'key2': 1, 'A1': 1, 'A2': 1, 'B1': 1, 'B2': 1}
さらに、
- 非破壊的に (元の辞書に変更を加えずに) 処理したい
- valueの変更をしない (keyが重複していたらエラーになってほしい)
これらを実現するための効率の良い書き方を紹介したいと思います。
良くない書き方
これは、.update()
と辞書の追加記法を使えば一部実現可能です。
dictA.update(dictB)
dictA['key1'] = 1
dictA['key2'] = 1
new_dict = dictA
print(new_dict)
# => {'A1': 1, 'A2': 1, 'B1': 1, 'B2': 1, 'key1': 1, 'key2': 1}
デメリット
元のdictAはなくなってしまいます。(dictAに要素の追加 (破壊的変更) をしているため)
print(dictA)
# => {'A1': 1, 'A2': 1, 'B1': 1, 'B2': 1, 'key1': 1, 'key2': 1}
また、keyが重複していると値が上書きされます。これは意図せぬ挙動(バグの原因)を引き起こす可能性があります。
dictA = {'key': 'dictA'}
dictB = {'key': 'dictB'}
dictA.update(dictB)
print(dictA)
# => {'key': 'dictB'}
適切な書き方
結合や要素の追加ということを気にせず、dict関数のキーワード引数に値を渡して新たに辞書をつくります。何個でも可能です。
new_dict = dict(
key1=1,
key2=1,
**dictA,
**dictB,
)
print(new_dict)
# => {'key1': 1, 'key2': 1, 'A1': 1, 'A2': 1, 'B1': 1, 'B2': 1}
非破壊的
非破壊的な処理なので元の辞書は変更を受けません。
new_dict['keyA1'] = 5
print(new_dict['keyA1'])
# => 5
print(dictA['keyA1'])
# => 1
重複がある場合の挙動
重複がある場合はTypeErrorになるので、意図しない値の上書きを回避できます。
辞書内のkeyと明示的に書いたキーワード引数すべての重複に対してエラーになります。
dictA = {'key': 'dictA'}
dictB = {'key': 'dictB'}
new_dict = dict(
key='A',
**dictA,
**dictB,
)
# => TypeError: type object got multiple values for keyword argument 'key'
まとめ
dict関数で作り直せば辞書の結合、要素の追加は安全かつ簡潔に書けますよ、という話でした!