この記事は最終更新日から1年以上が経過しています。
はじめに
昔、Pythonのリストのコピーでつまずいた話になります。
同じミスがないように。。。と思い共有します。
環境
- Python 3.6.3
リストのコピー
以下のようにリストを代入しただけだと
l1 = [1, 2, 3] l2 = l1 l2[0] = 10 #l2のみ最初の値を変えたい print('l1:', l1) print('l2:', l2) |
実行結果
l1: [10, 2, 3] l2: [10, 2, 3] |
l2だけを変更したつもりが、
l1まで変わってしまいました。
リストの場合、単純な代入だけでは同じオブジェクトを参照してしまいます。
C++を書いているときも似たようなことがあったので、コピーをしなければならないと思いました。
ということで、以下のようなコードで
import copy l1 = [1, 2, 3] l2 = copy.copy(l1) #コピーを行う l2[0] = 10 print('l1:', l1) print('l2:', l2) |
実行結果
l1: [1, 2, 3] l2: [10, 2, 3] |
コピーをすることで別のオブジェクトになり、ちゃんと l2の値だけが変わりました。
多次元リストのコピー
多次元のリストでも同じように書いたのですが
import copy l1 = [[1, 2, 3], [4, 5, 6]] l2 = copy.copy(l1) l2[0][0] = 10 print('l1:', l1) print('l2:', l2) |
実行結果
l1: [[10, 2, 3], [4, 5, 6]] l2: [[10, 2, 3], [4, 5, 6]] |
!?
l2だけを変えたつもりが、
l1まで変わってしまいました。
浅いコピーと深いコピー
Python(というかプログラミング全般)には浅いコピー
copyと深いコピー
deepcopyがあるようです。
浅いコピーでは、オブジェクト内のオブジェクトまでコピーをしてくれません。
深いコピーでは再帰的にコピーを行うため、以下のようなコードにしたら
import copy l1 = [[1, 2, 3], [4, 5, 6]] l2 = copy.deepcopy(l1) #深いコピーにする l2[0][0] = 10 print('l1:', l1) print('l2:', l2) |
実行結果
l1: [[1, 2, 3], [4, 5, 6]] l2: [[10, 2, 3], [4, 5, 6]] |
ちゃんと l2の値だけが変わってくれました。
まとめ
単純にコピーと言っても、浅いコピー(シャローコピー)と深いコピー(ディープコピー)がありました。
この記事を書いた人
- 2017年入社の新卒です。
最近書いた記事
- 2019.10.11Pythonのアンパックとタプル
- 2019.01.22JavaScript側でsubmitができない
- 2018.12.13「AWS Toolkit for PyCharm について」~ RecoChoku Tech Night #09 4社合同 AWS re:Invent参加レポート で登壇しました ~
- 2018.12.02シリコンバレー1日ツアーに参加してきました(前半)