mr-csce’s diary

ブログの説明

dict.fromkeys()で作成したdictのvalueのlistを編集するとすべてのkeyのlistが変わってしまう件

[Python] dict.fromkeys()で作成したdictのvalueのlistを編集するとすべてのkeyのlistが変わってしまう件

dict.fromkeys()とは

dict.fromkeys()は、下記のように同じ値をvalueに持つdict型のデータを作成します。

>>> test_dict = dict.fromkeys(["key1", "key2"], "value")
>>> test_dict
{'key1': 'value', 'key2': 'value'}

dict.fromkeys()で作成したdict型のデータと、普通のdict型のデータの違い

下記2つの辞書は一見同じに見えます。

>>> test_dict = dict.fromkeys(["a", "b", "c"], [])
>>> test_dict
{'a': [], 'b': [], 'c': []}

>>> test_dict2 = {"a": [], "b":[], "c":[]}
>>> test_dict2
{'a': [], 'b': [], 'c': []}

しかしながら厳密には異なります。 dict.fromkeys()では、valueがlistやdict型などmutableな型であっても完全に同じデータがvalueになります。

>>> test_dict = dict.fromkeys(["a", "b", "c"], [])
>>> test_dict
{'a': [], 'b': [], 'c': []}

言い換えると、各要素は同じメモリ領域に確保されています。

>>> id(test_dict["a"])
139793884250952
>>> id(test_dict["b"])
139793884250952
>>> id(test_dict["c"])
139793884250952

一方、下記のように素直にdict型のデータを生成した場合、各要素はそれぞれ別のメモリ領域に確保されます。

>>> test_dict2 = {"a": [], "b":[], "c":[]}
>>> test_dict2
{'a': [], 'b': [], 'c': []}

>>> id(test_dict2["a"])
139793884251016
>>> id(test_dict2["b"])
139793884251208
>>> id(test_dict2["c"])
139793884251528

したがって、両者の辞書は次のような違いが現れます。

>>> test_dict["a"].append("A")
>>> test_dict
{'a': ['A'], 'b': ['A'], 'c': ['A']}

>>> test_dict2["a"].append("A")
>>> test_dict2
{'a': ['A'], 'b': [], 'c': []}

結論

mutableな型をvalueに持つdict型のデータをdict.fromkeys()で作成する場合は注意が必要です。