0
2

More than 1 year has passed since last update.

変数や list の値をコピーする方法(copy()メソッド、deepcopy()関数)

Posted at

変数や list の値をコピーするには、
実現したい内容によっていくつかの方法があります。
私はそれを知らないまま1時間近く悩んでしまったことがあるので、
ここにまとめておきます。

ここでは、以下の3パターンに分けて説明します。

  1. 変数の値を代入
  2. list の浅いコピー(copy()メソッド)
  3. list の深いコピー(deepcopy()関数)

1. 変数の値を代入

変数の値を代入した場合のコードを例に説明します。

s = 1

# 変数の値を代入
d = s

# 代入元変数の値を変更し、その値を出力
s += 100
print("s -> ", s)

# 代入先変数の値を出力
print("d -> ", d)

実行結果は以下の通り。

s ->  101
d ->  1

実行結果を見てもわかるように、
代入元と代入先の変数は別々の変数として管理されているため、
片一方を変更しても、もう片方に影響はありません。

2. list の浅いコピー(copy()メソッド)

続いて list のコピーを行いますが、
まずはイケてないコピー方法の例を挙げます。

s_list = [0, 1, 2]

# list を代入
d_list = s_list

# 代入元 list の値を変更し、その値を出力
s_list[0] += 100
print("s_list -> ", s_list)

# 代入先 list の値を出力
print("d_list -> ", d_list)

実行結果は以下の通り。

s_list ->  [100, 1, 2]
d_list ->  [100, 1, 2]

実行結果を見てもわかるように、
代入元の list を変更しただけなのに、
代入先の list の値も変更してしまっています。
つまり同一のオブジェクトを参照してしまっています。

これを回避する(別のオブジェクトを参照する)には、
d_list = s_listという指定ではなく、
copy()メソッドを使い、
d_list = s_list.copy()と指定します。

具体的なコードを使って説明します。

s_list = [0, 1, 2]

# list を copy()メソッドでコピー
d_list = s_list.copy()

# 代入元 list の値を変更し、その値を出力
s_list[0] += 100
print("s_list -> ", s_list)

# 代入先 list の値を出力
print("d_list -> ", d_list)

実行結果は以下の通り。

s_list ->  [100, 1, 2]
d_list ->  [0, 1, 2]

今回はちゃんと別々の結果になっています。
つまり別々のオブジェクトを参照してます。

3. list の深いコピー(deepcopy()関数)

最後に、2次元 list のコピーを行いますが、
まずは直前に説明したcopy()メソッドを使ったイケてない例を挙げます。

s_list = [0, 1, [20, 21, 22]]

# list を copy()メソッドでコピー
d_list = s_list.copy()

# 代入元 list の値を変更し、その値を出力
s_list[0] += 100
s_list[2][0] += 100
print("s_list -> ", s_list)

# 代入先 list の値を出力
print("d_list -> ", d_list)

実行結果は以下の通り。

s_list ->  [100, 1, [120, 21, 22]]
d_list ->  [0, 1, [120, 21, 22]]

実行結果を見てもわかるように、
入れ子(2次元配列)になっていない部分(0番目)の値は別オブジェクトを参照していますが、
入れ子(2次元配列)になってる部分(2番目)の値は同じオブジェクトを参照しているため、
同じ値になっています。

これを回避する(別のオブジェクトを参照する)には、
copy モジュールの deepcopy() 関数を使います。

具体的なコードを使って説明します。

# copy モジュールを import
import copy

s_list = [0, 1, [20, 21, 22]]

# list を copy.deepcopy() 関数でコピー
d_list = copy.deepcopy(s_list)

# 代入元 list の値を変更し、その値を出力
s_list[0] += 100
s_list[2][0] += 100
print("s_list -> ", s_list)

# 代入先 list の値を出力
print("d_list -> ", d_list)

実行結果は以下の通り。

s_list ->  [100, 1, [120, 21, 22]]
d_list ->  [0, 1, [20, 21, 22]]

今回は入れ子(2次元配列)になってる部分(2番目)も含めて
別々の結果になっています。

知らないとかなりハマってしまう内容ですが(私はハマりました)、
整理して理解しておけば、難しくはない内容だと思います。
どなたかの参考になればと思います。

0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2