IndexError: list index out of range の原因と直し方[Python]
Pythonを書いていて頻繁に出会うのがこのエラーになる。
IndexError: list index out of range意味はそのままで、リストの範囲外の位置を取りに行った、ということだ。長さ3のリストにlst[3]でアクセスすると出る。Pythonのインデックスは0から始まるので、長さ3なら使えるのは0、1、2までになる。
原因はいくつかのパターンに分かれるので、順に見ていく。
1. ループの範囲が1つ多い
いちばん多いのがこれになる。
lst = [10, 20, 30]for i in range(len(lst) + 1): # 0,1,2,3 が回る print(lst[i]) # i=3 で IndexErrorrange(len(lst))は0から2までを返すのに、+1を足したせいで3まで回ってしまっている。
そもそもインデックスが不要なら、リストを直接回すのがいちばん安全になる。
for x in lst: print(x)インデックスも欲しいならenumerateを使う。これなら範囲を自分で計算しないので間違えようがない。
for i, x in enumerate(lst): print(i, x)2. リストが空だった
処理の途中でリストが空になっているのに気づかず、先頭を取りに行くパターンになる。
results = [x for x in data if x > 100]print(results[0]) # 条件に合うものが無いと IndexErrorフィルタした結果がゼロ件になるのは普通に起きるので、取り出す前に確認する。
if results: print(results[0])else: print("該当なし")デフォルト値が欲しいだけなら、nextを使う書き方も便利になる。
first = next((x for x in data if x > 100), None)ファイルを読んで分割した結果が空になっているケースもよくある。空行や末尾の改行が原因のことが多い。
parts = line.split(",")value = parts[1] # 空行だと parts は [''] なので IndexErrorparts = line.strip().split(",")if len(parts) >= 2: value = parts[1]3. ループ中にリストから要素を削除している
見つけにくいのがこれになる。回している最中にリストの長さが変わるので、途中で範囲外になる。
for i in range(len(lst)): if lst[i] < 0: lst.pop(i) # 削除するたびに len が減る → IndexError削除しながら回すのは避けて、新しいリストを作るのが定石になる。
lst = [x for x in lst if x >= 0]どうしても元のオブジェクトを保ちたい場合は、スライス代入で中身を入れ替える。
lst[:] = [x for x in lst if x >= 0]4. 二次元リストの行と列を取り違えている
行列を扱っているときに、行数と列数を逆にして回してしまうパターンになる。
matrix = [[1, 2, 3], [4, 5, 6]] # 2行3列for i in range(3): for j in range(2): print(matrix[i][j]) # i=2 で IndexError行数はlen(matrix)、列数はlen(matrix[0])になる。
for i in range(len(matrix)): for j in range(len(matrix[i])): print(matrix[i][j])行ごとに長さが違う可能性があるので、len(matrix[0])ではなくlen(matrix[i])にしておくと安全になる。
どこで落ちたかを特定する
原因がすぐわからないときは、落ちる直前の状態を出してしまうのが早い。
try: print(lst[i])except IndexError: print(f"len={len(lst)} i={i} lst={lst}") raise長さとインデックスを並べて見れば、1つ多いのか、そもそも空なのかはすぐ判別できる。
まとめ
・IndexErrorは存在しない位置を取りに行ったときのエラー。長さnのリストで使えるのは0からn-1まで
・ループ範囲の+1が最頻の原因。インデックスが不要なら直接ループ、必要ならenumerateを使う
・フィルタ結果や空行の分割で空リストになるケースは、取り出す前に長さを確認する
・ループ中の削除は範囲がずれる。内包表記で作り直すかlst[:]で入れ替える
・二次元では行数len(matrix)と列数len(matrix[i])を取り違えていないか確認する
・原因が読めないときはlenとインデックスを一緒に出力すると一発でわかる