
Table of Contents(目次)
Pythonのdictコピー時に同じオブジェクトを参照する場合の挙動
dictも、listやtupleなどと同じように変数から参照されて管理されています。ですので、d2 = d1
のようにコピーした場合、同じオブジェクトを参照することになるので、要素を変更すると他方にも他方にも影響します。
d1 = {'key1': 1, 'key2': 2}
d2 = d1
d2['key2'] = 10
d2['key3'] = 30
print('d1', d1, id(d1)) # d1 {'key1': 1, 'key2': 10, 'key3': 30} 2827504193216
print('d2', d2, id(d2)) # d2 {'key1': 1, 'key2': 10, 'key3': 30} 2827504193216
PythonのdictをShallow copyで複製する方法
dictにはlistやtupleのようなスライスは使えないので、copy()
メソッドを使います。これはShallow copy (シャローコピー/ 浅いコピー)ですので、ネストされたlistやdictは複製されません。
ネストされていない、またはネスト部分を編集しない場合は、copy()
メソッドで解決できます。
d1 = {'key1': 1, 'key2': 2}
d2 = d1.copy()
d2['key2'] = 10
d2['key3'] = 30
print('d1', d1, id(d1)) # d1 {'key1': 1, 'key2': 2} 3208174636736
print('d2', d2, id(d2)) # d2 {'key1': 1, 'key2': 10, 'key3': 30} 3208174647808
PythonのネストされたdictをShallow copyしたときの注意点
次のコードのような、ネストされたデータの場合の挙動を確認します。
d1 = {'profile': {'age': 10}, 'friends': ['Emma']}
d2 = d1.copy()
d2['profile']['age'] = 99
d2['friends'].append('NICOLAS')
print('d1', d1, id(d1)) # d1 {'profile': {'age': 99}, 'friends': ['Emma', 'NICOLAS']} 2464997588928
print('d2', d2, id(d2)) # d2 {'profile': {'age': 99}, 'friends': ['Emma', 'NICOLAS']} 2464997588864
print('d1["profile"]', d1['profile'], id(d1['profile'])) # d1["profile"] {'age': 99} 2464997576448
print('d2["profile"]', d2['profile'], id(d2['profile'])) # d2["profile"] {'age': 99} 2464997576448
print('d1["friends"]', d1['friends'], id(d1['friends'])) # d1["friends"] ['Emma', 'NICOLAS'] 2464997554752
print('d2["friends"]', d2['friends'], id(d2['friends'])) # d2["friends"] ['Emma', 'NICOLAS'] 2464997554752
"外側"のdictは、copy()
メソッドによって複製されるので、異なるidになります。しかし、valueとして定義されたdictやlistは同じオブジェクトを参照している為、それらのオブジェクトに対して編集が行われると、他方にまで影響が及びます。
(※ただし、ネストされたオブジェクトの要素を一切変更しない場合は、Shallow copyで十分です。)
PythonのネストされたdictをDeep copyする方法とShallow copyとの違い
次に、Deep copy(ディープコピー)した時の実行結果を確認しましょう。copyモジュールのdeepcopy()
関数を使用します。
import copy
d1 = {'profile': {'age': 10}, 'friends': ['Emma']}
d2 = copy.deepcopy(d1)
d2['profile']['age'] = 99
d2['friends'].append('NICOLAS')
print('d1', d1, id(d1)) # d1 {'profile': {'age': 10}, 'friends': ['Emma']} 1303331618752
print('d2', d2, id(d2)) # d2 {'profile': {'age': 99}, 'friends': ['Emma', 'NICOLAS']} 1303331618432
print('d1["profile"]', d1['profile'], id(d1['profile'])) # d1["profile"] {'age': 10} 1303331606336
print('d2["profile"]', d2['profile'], id(d2['profile'])) # d2["profile"] {'age': 99} 1303331618560
print('d1["friends"]', d1['friends'], id(d1['friends'])) # d1["friends"] ['Emma'] 1303331584640
print('d2["friends"]', d2['friends'], id(d2['friends'])) # d2["friends"] ['Emma', 'NICOLAS'] 1303331482048
ネストされたdictやlistなどのオブジェクトも含め、全てのidが異なっていることが確認できます。これで、ネストされたオブジェクトに対して編集を行っても、他方に影響を与えなくなります。
(※ ただし、全てを複製することによって、メモリ使用量や処理速度に影響が出ることがありますので、処理の内容によってShallow copyとDeep copyを使い分けましょう。)