66053


### 前提・実現したいこと

辞書のcopy()に変更を加えているのにかかわらず元の辞書も変更するのはなぜか？

また、fromkeys(辞書)に変更を加えると、指定したkey以外にも変更が加わるのはなぜか？

### copy()

copy()を使用したnew_dictsに変更を加えているのにもかかわらず、元のdictsも変更されている。

[code]

    dicts = {'A': [[0, 0]], 'B': [[3, 3]]}
    new_dicts = dicts.copy()
    
    new_dicts["A"].append(1)
    print(dicts)
    
    >> {'A': [[0, 0], 1], 'B': [[3, 3]]}
    
[/code]

### fromkeys(辞書)

キーは"A"を指定しているにもかかわらず、"B"の値まで変更されている。

[code]

    dicts = {'A': [[0, 0]], 'B': [[3, 3]]}
    new_dicts = dict.fromkeys(dicts,[])
    
    new_dicts["A"].append(1)
    print(new_dicts)
    
    >> {'A': [1], 'B': [1]}
    
[/code]


CC BY-SA 4.0
2020-04-28T04:39:14.420
66052
2020-04-28T07:03:18.520
question
python
辞書のcopy()とdict.fromkeys(辞書)の振る舞いについて知りたい


> 辞書のcopy()に変更を加えているのにかかわらず元の辞書も変更するのはなぜか？

[`copy()`が浅いコピー](https://docs.python.org/ja/3/library/stdtypes.html#dict.copy)だからです。新しい辞書オブジェクトが作られますが、辞書の中の値は共有されます。

[`copy.deepcopy(dicts)`](https://docs.python.org/ja/3/library/copy.html#copy.deepcopy)とすることで値もコピーになります。

* * *

> また、fromkeys(辞書)に変更を加えると、指定したkey以外にも変更が加わるのはなぜか？

[`fromkeys()`](https://docs.python.org/ja/3/library/stdtypes.html#dict.fromkeys)のマニュアルに書いてあります。

> All of the values refer to just a single instance, so it generally doesn't
> make sense for value to be a mutable object such as an empty list.

「辞書のすべてのエントリが同一の値を参照するため、空リストなどの変更可能なオブジェクトを指定するのは一般的に役に立ちません。」

リストを初期値としたい場合は、`fromkeys()`を使わないでループで初期化するか、

[code]

    new_dict = {key: [] for key in dicts.keys()}
    
[/code]

初期化を諦めて
[`setdefault()`](https://docs.python.org/ja/3/library/stdtypes.html#dict.setdefault)を使うといいかもしれません。

[code]

    new_dict = {}
    new_dict.setdefault("A", []).append(1)
    
[/code]


CC BY-SA 4.0
2020-04-28T05:18:20.793
66053
2020-04-28T07:03:18.520
2020-04-28T07:03:18.520
3475
3475
66052
answer