LoginSignup
2
2

【Python】エラー「IndexError: list index out of range」を出ないようにするorエラー捕捉するコード

Posted at

概要

IndexError: list index out of rangeエラーに遭遇し、このエラーを出ないようにするor捕捉してあげることでエラーをキャッチできるコードを3つ作成したので紹介します。

list index out of rangeとは

以下のコードを実行すると、リストの最初の要素のfruit_nameを取得できます。

def get_first_data_of_list(data, key, sub_key):
    value = ''
    if key in data:
        if sub_key in data[key][0]:
            value = data[key][0][sub_key]
    return value

information = {
    "fruit":
    [
        {"fruit_name" : "apple",
         "fruit_price" : "200" },
        {"fruit_name" : "banana",
         "fruit_price" : "100" }
    ],
}

value = get_first_data_of_list(information, "fruit", "fruit_name")
print(value) # apple

しかし、informationデータの中身が空で連携された場合、結果はどうなるでしょうか。

def get_first_data_of_list(data, key, sub_key):
    value = ''
    if key in data:
        if sub_key in data[key][0]:
            value = data[key][0][sub_key]
    return value

information = {
    "fruit":[],
}

value = get_first_data_of_list(information, "fruit", "fruit_name")
print(value) # apple

結果は以下。

    if sub_key in data[key][0]:
IndexError: list index out of range

上述の通り、list index out of rangeというインデックスエラーになってしまいました。

このエラーは、リストのインデックスの範囲外、存在しない値を使用して要素にアクセスしようとすると発生するエラーです。空のリストで何も要素がないのに、if sub_key in data[key][0]で1番目のインデックスにアクセスしようとしているため、「範囲外のインデックス」として上述のエラーが発生しました。

もっとわかりやすい例で言うと、以下のように、「範囲外のインデックス」の場合はこのエラーが発生します。

lst = [1, 2, 3]
print(lst[3])

空のリストでもエラーにならないコード1

以下のようにすると、空のリストが連携されてもエラーになりません。
これは、data[key][0]にアクセスする前に、data[key]がリストであることかつその長さが0より大きいことを条件としています。これにより、空のリストでもエラーが発生しないようにすることができます。

def get_first_data_of_list(data, key, sub_key):
    value = ''
    if key in data and isinstance(data[key], list) and len(data[key]) > 0:
        if sub_key in data[key][0]:
            value = data[key][0][sub_key]
    return value

information = {
    "fruit":[],
}

value = get_first_data_of_list(information, "fruit", "fruit_name")
print(value)  # apple

空のリストでもエラーにならないコード2

以下のコードでも、空のリストでエラーになりません。

def get_first_data_of_list(data):
    try:
        return data.get('fruit', [{}])[0].get('fruit_name', '')
    except IndexError:
        return ''

information = {
    "fruit":[],
}

value = get_first_data_of_list(information)
print(value)

このコードでは、getメソッドを使用して辞書からキーに対応する値を取得しています。getメソッドの第二引数は、キーが辞書に存在しない場合に返されるデフォルト値を指定します。
エラーについては、try/exceptブロックを使用して例外を捕捉してあげる形にしています。

空のリストでもエラーにならないコード3

以下は、Pythonの組み込み関数nextとジェネレータ式を使用して実現しているコードです。


def get_first_fruit_name(data):
    fruits = data.get('fruit', [])
    return next((item.get('fruit_name', '') for item in fruits if 'fruit_name' in item), '')

information = {
    "fruit":[],
}

value = get_first_fruit_name(information)
print(value)

ジェネレータはあまり使ったことがないですが、大量のデータを扱う場合や大量にforループを繰り返す際には、メモリを節約することができるらしいです。リスト全体をメモリにロードするのではなく、一度に1つの要素だけを生成するからですね。

上記では、next関数を使用して、fruit_nameキーを持つ最初の辞書のfruit_nameの値を取得。
next関数の第二引数は、ジェネレータが終了した(=fruit_nameキーを持つ辞書がない)場合に返されるデフォルト値を指定します。

参考:ジェネレータとnext関数の参考例

2の倍数を無限に生成するジェネレータ式から、一つずつ次の要素を取り出すコード:

gen = (i * 2 for i in range(100))

print(next(gen))  # 0を出力
print(next(gen))  # 2を出力
print(next(gen))  # 4を出力
2
2
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
2
2