変数と代入文(=)
オブジェクトを格納する箱ではなく、オブジェクトを参照するための名札をイメージすると良い
pythonの代入文は、オブジェクトそのものをコピーするのではなく、オブジェクトの参照をコピーする!
オブジェクトをコピー?参照をコピー?
>>> your_colar = ['red', 'bule', 'black']
>>>my_colar = your_colar
>>> your_colar
['red', 'bule', 'black']
>>> my_colar
['red', 'bule', 'black']
>>> your_colar[2] = 'green'
>>> your_colar
['red', 'bule', 'green']
>>> my_colar
['red', 'bule', 'green']
>>> id(your_colar), id(my_colar)
(1749125224128, 1749125224128)
オブジェクトそのものをコピーしているのではなく、オブジェクトの参照のみをコピーしている。
代入文が参照をコピーする理由
参照自体は数バイトしかサイズはないが、もしもリストにより多くの要素が入っている場合(何億とか)、リスト全体をコピーしてしまうと多くのメモリーを使用してしまうから。
参照を共有しないコピー(copy.copy()やcopy.deepcopy())
copy.copy()を使ってみよう!
>>> import copy
>>> your_colar = ['red', 'bule', 'black']
>>> my_colar = copy.copy(your_colar)
>>> id(your_colar), id(my_colar)
(1749125224128, 1749125306752)
>>> your_colar[2] = 'green'
>>> your_colar
['red', 'bule', 'green']
>>> my_colar
['red', 'bule', 'black']
your_colarを変更しても、my_colarに影響を及ぼしていないことがわかる
入れ子のリストはどうだろうか?
>>> import copy
>>> your_num = [[1, 2], [3, 4]]
>>> my_num = copy.copy(your_num)
>>> id(your_num), id(my_num)
(1749125307776, 1749125306112)
>>> your_num.append('APPEND_NUM')
>>> your_num
[[1, 2], [3, 4], 'APPEND_NUM']
>>> my_num
[[1, 2], [3, 4]]
>>> your_num[0][0] = 100
>>> your_num
[[100, 2], [3, 4], 'APPEND_NUM']
>>> my_num
[[100, 2], [3, 4]]
your_numとmy_numは、違うリストオブジェクトであるが、内部にあるリストは参照先が同じことがわかる!!
copy.deepcopy()をしよう!!
★copy.deepcopy()を使うとリスト内部にあるリストまでもコピーすることができる★
>>> import copy
>>> your_num = [[1, 2], [3, 4]]
>>> my_num = copy.deepcopy(your_num)
>>> id(your_num), id(my_num)
(1749125308352, 1749125307776)
>>> your_num[0][0] = 100000000
>>> your_num
[[100000000, 2], [3, 4]]
>>> my_num
[[1, 2], [3, 4]]
リストの内部に他の可変型オブジェクトが含まれているかわからないときは、deepcopy()で対応しよう!
若干、速度低下を引き起こすが、常にdeepcopy()を使う癖をつけておくと、いいかも??