2018年3月27日火曜日

追記有り。

この事態を Python で避ける方法。

まず、なぜそうなるかということを書こうと思ったら、既出。

Python 3 に 「===」演算子はないから、わかりやすくイメージ図を追加。

a a a 0,1 a a 0 a 0 (

MyScript Nebo(iPad アプリ)、Nebo(Windows アプリ)を使って描いてみた。まだダイアグラムの描画をうまく使えるようになってない…)

BIF(built-in function) の id 関数でも確認。

コード(Emacs)

Python 3

#!/usr/bin/env python3

a = [[0] * 3] * 3

print(f'a: {a}')
for i, t in enumerate(a):
    print(f'a[{i}]: {id(t)}')
print()

a[0][0] = 1
print(f'a: {a}')
for i, t in enumerate(a):
    print(f'a[{i}]: {id(t)}')

a = [[0] * 3 for _ in range(3)]
print(f'a: {a}')
for i, t in enumerate(a):
    print(f'a[{i}]: {id(t)}')
print()

a[0][0] = 1
print(f'a: {a}')
for i, t in enumerate(a):
    print(f'a[{i}]: {id(t)}')

入出力結果(Terminal, Jupyter(IPython))

$ ./sample1.py
a: [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
a[0]: 4387831176
a[1]: 4387831176
a[2]: 4387831176

a: [[1, 0, 0], [1, 0, 0], [1, 0, 0]]
a[0]: 4387831176
a[1]: 4387831176
a[2]: 4387831176
a: [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
a[0]: 4387940680
a[1]: 4387828872
a[2]: 4387942152

a: [[1, 0, 0], [0, 0, 0], [0, 0, 0]]
a[0]: 4387940680
a[1]: 4387828872
a[2]: 4387942152
$

ということで、どのように解決するか。

コード(Emacs)

Python 3

#!/usr/bin/env python3

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

a[0][0] = 1

print(a)

入出力結果(Terminal, Jupyter(IPython))

$ ./sample.py
[[1, 0, 0], [0, 0, 0], [0, 0, 0]]
$

リスト内包表記を使えば、リストの各要素(リスト)が同じものではなく、別々のリストってことがはっきりするし、優先順位を気にする必要もなくなる(し、読みやすくなる(?))。

(タイプ数は多くなるけど...>_<)

0 コメント:

コメントを投稿