shallow copy, deep copy

January 31, 2021

shallow copy, deep copy

3点リーダのことを調べてたときにshallow copy, deep copyについてでてきたので記載しておきます。
pythonでは、numpyの配列に限らず配列はshallow copyされます。shallow copyとは、データの存在場所(アドレス)だけがコピーされるコピー手段です。

>>> a = [1, 2, 3]
>>> b = a
>>> hex(id(a))
'0x7f6ccd91cd88'
>>> hex(id(b))
'0x7f6ccd91cd88'

b = aだとshallow copyになるので、id(データの存在場所)は同じになります。なので、aを変更するとbも変わってしまいます。

>>> a[0] = 4
>>> a
[4, 2, 3]
>>> b
[4, 2, 3]
>>>

上記を試すうえで注意しなければならいのは、a = [4, 2, 3]と値を変えてはいけないということです。a = [4, 2, 3]とやってしまうと、[4, 2, 3]用に新しいアドレスが割り当てられ、aにそれが代入されてしまうからです。

>>> a = [1, 2, 3]
>>> b = a
>>> hex(id(a))
'0x7f6ccd91cd48'
>>> hex(id(b))
'0x7f6ccd91cd48'  # aとbは一緒
>>> a = [4, 2, 3]
>>> hex(id(a))
'0x7f6ccd91cc88'  # aのアドレスが変わる
>>> hex(id(b))
'0x7f6ccd91cd48'  # bのアドレスは変わらない
>>> a
[4, 2, 3]
>>> b
[1, 2, 3]
>>>

参照先が同じかどうかを確認する手段としてisがあります。

>>> a = [1, 2, 3]
>>> hex(id(a))
'0x7f51da75c048'
>>> b = [1, 2, 3]
>>> hex(id(b))
'0x7f51da7d39c8'
>>> a == b  # [1, 2, 3]と[1, 2, 3]は値として同じなのでTrueとなる
True
>>> a is b  # 0x7f51da75c048と0x7f51da7d39c8は参照先(実体)が違うのでFalseとなる
False
>>>

deep copyは、コピー元の変更がコピー先に影響しないというメリットがありますが、コピー先専用の存在場所が必要になるためメモリーを消費するというデメリットがあります。