Pythonで二次元配列(多次元リスト)を初期化するとき、[[0]*W]*H
を使っていませんか?
それ、バグの温床です! 本記事では、正しい初期化方法とその理由を、コード例つきでわかりやすく解説します。
✅ 結論:Pythonでの二次元配列の安全な初期化方法
dp = [[0] * W for _ in range(H)]
この形がベストです。なぜこれが正しくて、他の方法が危険なのか? 以下で詳しく解説します。
❌ 初心者がやりがちな間違い:[[0]*W]*H
の落とし穴
🔍 サンプルコード
W = 3
H = 2
dp = [[0]*W]*H
dp[0][0] = 1
print(dp)
🧨 出力結果
[[1, 0, 0], [1, 0, 0]]
なんと、1行目だけ書き換えたはずが、2行目まで変わってしまいました。
🧠 原因:リストの「参照コピー」が発生している
Pythonの [[0]*W]*H
は、同じリストオブジェクトをH個コピーしているだけ。
つまり、すべての行が同じメモリ(参照)を指しているので、1行を変更すると他の行にも影響します。
✅ 正しい初期化:for文で独立したリストを生成する
dp = [[0] * W for _ in range(H)]
✔ サンプルコード
W = 3
H = 2
dp = [[0]*W for _ in range(H)]
dp[0][0] = 1
print(dp)
🎯 出力結果
[[1, 0, 0], [0, 0, 0]]
期待通り、1行目だけが更新されました。
🛠 実践サンプル:動的計画法(DP)テーブルの初期化
二次元配列の初期化は、動的計画法(DP)などのアルゴリズム実装でもよく使います。
W, H = 5, 5
dp = [[0]*W for _ in range(H)]
# スタートから右下に向かうパスの数(右・下のみ移動)
for i in range(H):
for j in range(W):
if i == 0 and j == 0:
dp[i][j] = 1
else:
if i > 0:
dp[i][j] += dp[i-1][j]
if j > 0:
dp[i][j] += dp[i][j-1]
for row in dp:
print(row)
📝 まとめ:Pythonの二次元配列は「参照」に注意!
書き方 | 安全性 | 説明 |
---|---|---|
[[0]*W]*H | ❌ 危険 | 同じリストを参照してしまう |
[[0]*W for _ in range(H)] | ✅ 安全 | 毎回新しいリストを生成する |