lisz-works

プログラミングと興味を貴方に

Python3 リストのコピー方法による動作の違い

【スポンサーリンク】

Python

こんにちわlisです!

今回はPython3での、リスト(list)のコピーについてです!

代入やコピーを行ったとき、値コピーなのか参照コピーなのか……

と、わかったつもりでいて、少し離れると訳わからなくなるので試しがてらまとめてみました。

ちなみに辞書型(dict)も恐らく同じです。

結論

今回試した結果はこちら。

コピーの仕方 結果
代入 d = s 参照がコピーされる
値代入 d[:] = s 値がコピーされる
浅いコピー d = copy.copy(s) 別オブジェクトでコピーされる
深いコピー d = copy.deepcopy(s) 別オブジェクトでコピーされる

それでは解説です。

下準備

まず準備として、元となるリストを作成しました。

>>> src_arr = [1, 2, 3]
>>> id(src_arr)
1347790259016

こいつを代入やコピーをして、どうなるかを見ていきます。

リストをそのまま代入したとき

代入元(src_arr)と代入先(arr1)のリストを作成します。

これを単純に代入した場合です。

>>> arr1 = []
>>> id(arr1)
1347790269320
>>> arr1 = src_arr
>>> id(arr1)
1347790259016
>>> id(src_arr)
1347790259016

結果は、src_arrと同じidになりました。

ということは参照(アドレス)がコピーされているため、arr1を操作するとsrc_arrも同じ操作を受けます。

参照が同じだからです。

>>> arr1[1] = 99
>>> arr1
[1, 99, 3]
>>> src_arr
[1, 99, 3]

リストの値をコピーする

今度は同じ代入でも「[:]」を付けて代入します。

>>> arr2 = []
>>> id(arr2)
1347790269320
>>> arr2[:] = src_arr
>>> id(arr2)
1347790269320
>>> id(src_arr)
1347790259016

するとidはそのままに、値はコピーがされています。

>>> arr2
[1, 2, 3]
>>> src_arr
[1, 2, 3]

この状態でarr2の配列を操作しても、src_arrには影響がありません。

作業が異なりますからね。

>>> arr2[1] = 99
>>> arr2
[1, 99, 3]
>>> src_arr
[1, 2, 3]

copy.copy(浅いコピー)

今度はcopy.copy()を使って、浅いコピーを試します。

>>> import copy
>>> arr3 = []
>>> id(arr3)
1347790269256
>>> arr3 = copy.copy(src_arr)
>>> id(arr3)
1347790269320
>>> id(src_arr)
1347790259016

結果はsrc_arrとも元のarr3とも異なるidとなりました。

新しいid(オブジェクト)にコピーした値が作られて、arr3に代入された感じです。

なので配列を操作しても、影響はありません。

>>> arr3
[11, 88, 3]
>>> src_arr
[1, 2, 3]
>>> arr3[1] = 99
>>> src_arr[1] = 88
>>> arr3
[11, 99, 3]
>>> src_arr
[1, 88, 3]

更にいうと、元のarr3のid(参照)をコピーしておいて、各々配列を操作すると、独立したオブジェクトであることがわかります。

>>> a = []
>>> a = arr3
>>> arr3 = copy.copy(src_arr)
>>>
>>> a[0] = 10
>>> arr3[0] = 11
>>> src_arr[0] = 12
>>> a
[10, 99, 3]
>>> arr3
[11, 88, 3]
>>> src_arr
[12, 88, 3]

copy.deepcopy(深いコピー)

copy.deepcopy()を使って、深いコピーを試します。

>>> arr4 = []
>>> id(arr4)
1347790269256
>>> arr4 = copy.deepcopy(src_arr)
>>> id(arr4)
1347790291656
>>> id(src_arr)
1347790259016

浅いコピー同様、どれとも一致しないidとなりました。

これも同じく各々独立したオブジェクトとしてコピーがされました。

>>> arr4
[1, 2, 3]
>>> src_arr
[1, 2, 3]
>>> arr4[1] = 99
>>> src_arr[1] = 88
>>> arr4
[1, 99, 3]
>>> src_arr
[1, 88, 3]
>>>
>>> b = []
>>> b = arr4
>>> arr4 = copy.deepcopy(src_arr)
>>>
>>> b[0] = 10
>>> arr4[0] = 11
>>> src_arr[0] = 12
>>> a
[10, 99, 3]
>>> arr4
[11, 88, 3]
>>> src_arr
[12, 88, 3]

あとがき

今回はPython3での、リストのコピーについてでした!

こう並べてみるとなるほどって感じです。

が、少し離れると忘れるときがあるので、メモですね。

みなさんももし忘れたら参考にしてみてください!

インタプリタでちゃちゃっと試した方が早いかもしれませんが(笑)

www.lisz-works.com