1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【Python】多次元リストのコピー

Posted at

Pythonの多次元リストのコピーについて、その挙動が自分にとっては理解しづらいので実験結果とともに整理。
結論から言うと、copy()リスト[:]、copyライブラリのcopy.copy()は浅いコピー(shallow copy)であり、新たな多次元リストを作成し、その後元のリスト中に見つかったリストに対する参照を挿入する。
copyライブラリのcopy.deepcopy()は深いコピー(deep copy)であり、新たな多次元リストを作成し、その後元のリスト中に見つかったリストのコピーを挿入する。

###copy()
「1層目」というのがいいのか、「1次元目」というのがいいのかよくわからないが…。コピーによって別の多次元リストができるので、IDは当然別のものになる。しかしそのリストの中身は参照なので、コピーの1層目を書き換えてもオリジナルのリストにその影響はないが、2層目以降の書き換えはIDが違うのにもかかわらずオリジナルにも波及する。

copy()
lst = [[0]*3 for _ in range(3)]

lst1 = lst.copy()

lst1[1] = ['r'] * 3
print('lst1 = ', lst1)
print('id(lst1) = %d' % id(lst1))
print('lst = ', lst)
print('id(lst) = %d' % id(lst))

lst1[0][1] = 'r'
print('lst1 = ', lst1)
print('id(lst1) = %d' % id(lst1))
print('lst = ', lst)
print('id(lst) = %d' % id(lst))
出力
lst1 =  [[0, 0, 0], ['r', 'r', 'r'], [0, 0, 0]]
id(lst1) = 139730947400512
lst =  [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
id(lst) = 139730946890944
lst1 =  [[0, 'r', 0], ['r', 'r', 'r'], [0, 0, 0]]
id(lst1) = 139730947400512
lst =  [[0, 'r', 0], [0, 0, 0], [0, 0, 0]]
id(lst) = 139730946890944

###リスト[:]
copy()と同様。

リスト[:]
lst = [[0]*3 for _ in range(3)]

lst1 = lst[:]

lst1[1] = ['r'] * 3
print('lst1 = ', lst1)
print('id(lst1) = %d' % id(lst1))
print('lst = ', lst)
print('id(lst) = %d' % id(lst))

lst1[0][1] = 'r'
print('lst1 = ', lst1)
print('id(lst1) = %d' % id(lst1))
print('lst = ', lst)
print('id(lst) = %d' % id(lst))
出力
lst1 =  [[0, 0, 0], ['r', 'r', 'r'], [0, 0, 0]]
id(lst1) = 140313735131456
lst =  [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
id(lst) = 140313734622336
lst1 =  [[0, 'r', 0], ['r', 'r', 'r'], [0, 0, 0]]
id(lst1) = 140313735131456
lst =  [[0, 'r', 0], [0, 0, 0], [0, 0, 0]]
id(lst) = 140313734622336

###copyライブラリcopy.copy()
copy()と同様。

copy.copy()
import copy

lst = [[0]*3 for _ in range(3)]

lst1 = copy.copy(lst)

lst1[1] = ['r'] * 3
print('lst1 = ', lst1)
print('id(lst1) = %d' % id(lst1))
print('lst = ', lst)
print('id(lst) = %d' % id(lst))

lst1[0][1] = 'r'
print('lst1 = ', lst1)
print('id(lst1) = %d' % id(lst1))
print('lst = ', lst)
print('id(lst) = %d' % id(lst))
出力
lst1 =  [[0, 0, 0], ['r', 'r', 'r'], [0, 0, 0]]
id(lst1) = 139783910001664
lst =  [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
id(lst) = 139783910057280
lst1 =  [[0, 'r', 0], ['r', 'r', 'r'], [0, 0, 0]]
id(lst1) = 139783910001664
lst =  [[0, 'r', 0], [0, 0, 0], [0, 0, 0]]
id(lst) = 139783910057280

###copyライブラリcopy.deepcopy()
コピーによって別の多次元リストができるのでIDは別のものになり、そのリストの中身もコピーされる。いわば、クローンが作られる。全く同じ内容だが別のものなので、それを書き換えてもオリジナルには影響がない。

copy.deepcopy()
import copy

lst = [[0]*3 for _ in range(3)]

lst1 = copy.deepcopy(lst)

lst1[1] = ['r'] * 3
print('lst1 = ', lst1)
print('id(lst1) = %d' % id(lst1))
print('lst = ', lst)
print('id(lst) = %d' % id(lst))

lst1[0][1] = 'r'
print('lst1 = ', lst1)
print('id(lst1) = %d' % id(lst1))
print('lst = ', lst)
print('id(lst) = %d' % id(lst))
出力
lst1 =  [[0, 0, 0], ['r', 'r', 'r'], [0, 0, 0]]
id(lst1) = 139629482679488
lst =  [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
id(lst) = 139629482735040
lst1 =  [[0, 'r', 0], ['r', 'r', 'r'], [0, 0, 0]]
id(lst1) = 139629482679488
lst =  [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
id(lst) = 139629482735040

###参考
Python - リストを複製する
copy --- 浅いコピーおよび深いコピー操作
【Python】 自分で作った関数の引数にリストを代入すると、そのオリジナルのリストが改変されてしまうのを防ぐ方法

1
0
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
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?