Start learning free

LESSON 101 OF 410 · LISTS I

IndexError: List Index Out of Range in Python

Lesson Read the full explanation

When accessing list data with indices, the most common problem we can run into is exceeding the list's bounds.

Remember, the items of a list are normally indexed from 0 to length - 1.

Any index which is strictly greater than length - 1 is invalid.

When you try to access an item with an invalid index, Python throws an error:

myList = [1, 2, 3]

# Valid indices: 0, 1, 2
print(myList[0]) # Output: 1
print(myList[2]) # Output: 3

# Invalid indices: 3, 30
print(myList[3]) # IndexError
print(myList[30]) # IndexError

Each of the last 2 accesses will produce an IndexError: list index out of range.


Negative indices:

Remember that in Python, we can also access items of a list using negative indices.

The valid negative indices are between -length and -1.

Any index which is strictly less than -length is invalid:

myList = [1, 2, 3]

# Valid indices: -1, -2, -3
print(myList[-1]) # Output: 3
print(myList[-3]) # Output: 1

# Invalid indices: -4, -10
print(myList[-4]) # IndexError
print(myList[-10]) # IndexError

Each of the last 2 accesses will produce an IndexError: list index out of range.

As programmers, we always want to make sure that we don't exceed one array's bounds in our programs


Assignment
Follow the Coding Tutorial and let's play with some arrays.


Hint
Look at the examples above if you get stuck.


STEP 1 OF 1
    Ctrl + Enter to check

    PYTHON · LISTS I

    Exceeding Array Bounds in Python, explained

    What exceeding a list's bounds means

    A Python list with n items has valid positive indices from 0 to n - 1. Python also accepts negative indices, which count from the end: valid ones run from -n to -1. Any index outside those two ranges is out of bounds, and reading it raises an error.

    my_list = [1, 2, 3]
    
    print(my_list[0])    # 1
    print(my_list[2])    # 3
    print(my_list[-1])   # 3
    print(my_list[-3])   # 1
    
    print(my_list[3])    # IndexError: list index out of range
    print(my_list[-4])   # IndexError: list index out of range
    

    The error is an IndexError with the message list index out of range. The message is the same whether the index was too large or too negative, so it does not tell you the index or the length; you have to print them.

    Why it happens

    The most common cause is forgetting that counting starts at 0. A list of 4 items has indices 0, 1, 2 and 3, so its length, 4, is not a valid index. The same off-by-one error appears in loops that run one step too far, such as for i in range(len(items) + 1).

    An empty list is a second source. It has no valid index at all, so [][0] and [][-1] both raise IndexError. This surprises people who write items[-1] to get "the last item" without checking that the list has any.

    The exercise: print the last element

    The lesson shows a program that should print the last element of ages, which is 21, but crashes:

    ages = [14, 32, 50, 21]
    
    print(ages[len(ages)])
    

    Here len(ages) is 4, and ages[4] does not exist. The last item is always at index len(ages) - 1, which is 3 here. The fix is one subtraction:

    ages = [14, 32, 50, 21]
    
    print(ages[len(ages) - 1])
    

    This prints 21. In Python there is an even shorter spelling, ages[-1], which also prints 21 because negative indices count from the end. Both are correct. len(ages) - 1 is the form that works in most languages, which is why the lesson uses it.

    Other places the same error appears

    The error is not limited to reading from lists. Each of these raises an IndexError as well, with a slightly different message:

    • Strings: "abc"[3] gives string index out of range.
    • Tuples: (1, 2)[2] gives tuple index out of range.
    • Assigning to a position: a = [1, 2, 3] followed by a[3] = 9 gives list assignment index out of range. Assignment never makes a list longer; use append for that.
    • pop: [1, 2, 3].pop(5) gives pop index out of range, and [].pop() gives pop from empty list.

    NumPy arrays

    If you use NumPy, the message names the index and the size. For a = np.array([1, 2, 3]), reading a[3] gives IndexError: index 3 is out of bounds for axis 0 with size 3. In a two-dimensional array the axis number says which dimension is too small: np.zeros((2, 2))[0, 2] reports axis 1 with size 2. The rule is the same as for lists: valid indices are -size to size - 1.

    What does not raise an error

    Slices are forgiving. A slice that goes past the end is trimmed instead of failing:

    my_list = [1, 2, 3]
    print(my_list[1:10])   # [2, 3]
    print(my_list[5:])     # []
    

    Also, list.insert with a large position does not fail: a.insert(10, 4) on [1, 2, 3] simply appends and gives [1, 2, 3, 4]. These calls can hide a wrong index, so they do not replace checking your indices.

    How to avoid it

    • Loop over the items directly (for item in items) when you do not need the position, or use for i, item in enumerate(items) when you do. Then there is no index to get wrong.
    • When you do need indices, use range(len(items)), whose last value is len(items) - 1.
    • Before reading items[-1] or items[0], check that the list is not empty: if items:.
    • When you catch the error in the wild, print len(items) and the index just before the failing line, and compare them.

    Key takeaways

    • Valid indices for a list of length n are 0 to n - 1 and -n to -1.
    • The last item is items[len(items) - 1] or items[-1].
    • items[len(items)] is always out of bounds.
    • Reading or assigning an index outside a list raises IndexError, while slicing never does.
    Keep going with PythonAbout 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free