[Python3] リストをコピーするときの注意点

Pythonで、リストをコピーして使いたい。
でも、コピー先のリストを変更すると、
コピー元のリストも変更されてしまう。

a = [1, 2, 3, 4]
b = a

b[1] = 8

print('list a = ', end='')
print(a)
print('list b = ', end='')
print(b)

---- 出力結果 ------
list a = [1, 8, 3, 4]
list b = [1, 8, 3, 4]

リスト “b[1]” を変更しただけなのに、
“a[1]” も変更されてしまっている。

その解説と解決法を、
下記のページでしてくれてました。

【Python】 リストを変数に代入する際に気をつけること(参照渡し、copyによるコピー)

↑↑が起こらないようにするためには、
リストの “copy()” メソッドを使うか、
copyモジュールを使う。

a = [1, 2, 3, 4]
b = a.copy()

b[1] = 8

print('list a = ', end='')
print(a)
print('list b = ', end='')
print(b)

---- 出力結果 ------
list a = [1, 2, 3, 4]
list b = [1, 8, 3, 4]

これが、例えば2次元リストだったらどうなるか、
試してみたいと思います。

2次元リストをコピーする場合

import copy

list2d = [
    [1, 2, 3, 4], 
    [5, 6, 7, 8]
]
copy2d = copy.copy(list2d)

copy2d[0][1] = 10

print('list2d = ', end='')
print(list2d)
print('copy2d = ', end='')
print(copy2d)

---- 出力結果 ------
list2d = [[1, 10, 3, 4], [5, 6, 7, 8]]
copy2d = [[1, 10, 3, 4], [5, 6, 7, 8]]

また、逆戻りで、”copy2d” を変更したら、
“list2d” も変わってしまいました。

idを見てみると、

(~前半部分省略~)

print('id of list2d = ', end='')
print(id(list2d))
print('id of copy2d = ', end='')
print(id(copy2d))

print('id of list2d[0] = ', end='')
print(id(list2d[0]))
print('id of copy2d[0] = ', end='')
print(id(copy2d[0]))

---- 出力結果 ------
id of list2d = 140066356255368
id of copy2d = 140066356255304
id of list2d[0] = 140066356233096
id of copy2d[0] = 140066356233096

2次元リスト自体のIDは異なっているが、
各行のIDは同じらしい。

これは、リストの”copy()” メソッドを使っても、
同じ結果になる。

この場合は、
“copy.deepcopy()”を使えばいい。

import copy

list2d = [
    [1, 2, 3, 4], 
    [5, 6, 7, 8]
]
copy2d = copy.copy(list2d)

copy2d[0][1] = 10

print('list2d = ', end='')
print(list2d)
print('copy2d = ', end='')
print(copy2d)

---- 出力結果 ------
list2d = [[1, 2, 3, 4], [5, 6, 7, 8]]
copy2d = [[1, 10, 3, 4], [5, 6, 7, 8]]

うまくいきました。

m×nの2次元リストを作る場合

要素がすべて0の、
m×n の2次元リストを作る場合、

a = [[0]*n]*m

ってしたいんですけど、

list2d = [[0]*4]*5

list2d[2][3] = 1

print('list2d = ', end='')
print(list2d)

print(id(list2d[0]))
print(id(list2d[1]))

---- 出力結果 ------
list2d = [[0, 0, 0, 1], [0, 0, 0, 1], [0, 0, 0, 1], [0, 0, 0, 1], [0, 0, 0, 1]]
140489141757064
140489141757064

↑↑↑と同じようになります。

これは、コピー元の2次元リストがなく、
“copy.deepcopy()”を使うわけにはいかない。
ので、

list2d = [[0]*4 for i in range(5)]

list2d[2][3] = 1

print('list2d = ', end='')
print(list2d)

---- 出力結果 ------
list2d = [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 1], [0, 0, 0, 0], [0, 0, 0, 0]]

ってすればいいのかな?
と思います。

コメントを残す

メールアドレスが公開されることはありません。