えびしブログ

〜サーバーは魔法で動いているわけではない〜

Pythonでリストの深いコピー

Pythonのリストの代入は参照渡しなので、普通に代入すると内容は同じものを指します。

>>> hoge = [1, 2, 3]
>>> fuga = hoge
>>> id(hoge)
4359788304
>>> id(fuga)
4359788304
>>>

参照を渡すだけでなく、複製したい場合は以下のようなやりかたでできます。

>>> hoge = [1, 2, 3]
>>> fuga = list(hoge)  # その1
>>> piyo = hoge[:]  # その2
>>> id(hoge)
4359425992
>>> id(fuga)
4359327896
>>> id(piyo)
4359788304
>>> import copy
>>> moga = copy.copy(hoge)  # その3
>>> id(moga)
4359328544

ただし、リストの中身が辞書のような参照先のあるオブジェクトである場合は、上記の方法でリストのコピーができても、中身の辞書は参照先が渡されるためコピーできません。

>>> hoge = [{"a": 1}]
>>> fuga = list(hoge)
>>> id(hoge[0])
140553539258480
>>> id(fuga[0])
140553539258480

中身もコピーしたい場合はcopyモジュールのdeepcopy関数を利用します。

8.17. copy — 浅いコピーおよび深いコピー操作 — Python 2.7ja1 documentation

>>> hoge = [{"a": 1}]
>>> import copy
>>> fuga = copy.deepcopy(hoge)
>>> id(hoge[0])
140553539161136
>>> id(fuga[0])
140553539260496

こういうコピーを「深いコピー」というそうです。

「ちゃんとリストをコピーしたはずなのに中身の辞書が同じものを指してるっぽい!なんで??」と悩んだことがあったため記録しておきます。

おわり。