You are reading solutions / Python
alfie-grace-headshot-square.jpg
Author: Alfie Grace
Data Scientist

TypeError: list indices must be integers or slices, not str

TypeError: list indices must be integers or slices, not str

Why does this occur?

This error occurs when using a string for list indexing instead of indices or slices. For a better understanding of list indexing, see the image below, which shows an example list labeled with the index values:

example_list_indexing.jpg

Using indices refers to the use of an integer to return a specific list value. For an example, see the following code, which returns the item in the list with an index of 4:

value = example_list[4] # returns 8

Using slices means defining a combination of integers that pinpoint the start-point, end-point and step size, returning a sub-list of the original list. See below for a quick demonstration of using slices for indexing. The first example uses a start-point and end-point, the second one introduces a step-size (note that if no step-size is defined, 1 is the default value):

value_list_1 = example_list[4:7]   # returns indexes 4, 5 and 6 [8, 1, 4]
value_list_2 = example_list[1:7:2] # returns indexes 1, 3 and 5 [7, 0, 1]

As a budding Pythoneer, one of the most valuable tools in your belt will be list indexing. Whether using indices to return a specific list value or using slices to return a range of values, you'll find that having solid skills in this area will be a boon for any of your current or future projects.

Today we'll be looking at some of the issues you may encounter when using list indexing. Specifically, we'll focus on the error TypeError: list indices must be integers or slices, not str, with some practical examples of where this error could occur and how to solve it.

Cause 1: Unconverted Strings

For a quick example of how this could occur, consider the situation you wanted to list your top three video games franchises. In this example, let's go with Call of Duty, Final Fantasy and Mass Effect. We can then add an input to the script, allowing the user to pick a list index and then print the corresponding value. See the following code for an example of how we can do this:

favourite_three_franchises = ['Call of Duty', 'Final Fantasy', 'Mass Effect']

choice = input('Which list index would you like to pick (0, 1, or 2)? ')

print(favourite_three_franchises[choice])
Out:
Which list index would you like to pick (0, 1, or 2)?  0
Out:
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-1-34186a0c8775> in <module>
      3 choice = input('Which list index would you like to pick (0, 1, or 2)? ')
      4 
----> 5 print(favourite_three_franchises[choice])

TypeError: list indices must be integers or slices, not str

We're getting the TypeError in this case because Python is detecting a string type for the list index, with this being the default data type returned by the input() function. As the error states, list indices must be integers or slices, so we need to convert our choice variable to an integer type for our script to work. We can do this by using the int() function as shown below:

Solution

favourite_three_franchises = ['Call of Duty', 'Final Fantasy', 'Mass Effect']

choice = int(input('Which list index would you like to pick (0, 1, or 2)? '))

print(favourite_three_franchises[choice])
Out:
Which list index would you like to pick (0, 1, or 2)?  1
Out:
Final Fantasy

Our updated program is running successfully now that 1 is converted from a string to an integer before using the choice variable to index the list, giving the above output.

Cause 2: Treating Lists as Dictionaries

Building on the previous example, let's create a list of JSON objects. In this list, each object will store one of the game franchises used previously, along with the total number of games the franchise has sold (in millions). We can then write a script to output a line displaying how many games the Call of Duty franchise has sold.

favourite_three_franchises = [
  {
    "Name" : "Call of Duty", 
    "Units Sold" : 400
  },
  {
    "Name" : "Final Fantasy",
    "Units Sold" : 150
  },
  {
    "Name" : "Mass Effect",
    "Units Sold" : 16
  }
]

if favourite_three_franchises["Name"] == 'Call of Duty':
    print(f'Units Sold: {favourite_three_franchises["Units Sold"]} million')
Out:
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-4-f61f169290d0> in <module>
     14 ]
     15 
---> 16 if favourite_three_franchises["Name"] == 'Call of Duty':
     17     print(f'Units Sold: {favourite_three_franchises["Units Sold"]} million')
TypeError: list indices must be integers or slices, not str

This error occurs because we have accidentally tried to access the dictionary using the "Name" key, when the dictionary is inside of a list. To do this correctly, we need first to index the list using an integer or slice to return individual JSON objects. After doing this, we can use the "Name" key to get the name value from that specific dictionary. See below for the solution:

Solution

for i in range(len(favourite_three_franchises)):
    if favourite_three_franchises[i]["Name"] == 'Call of Duty':
        print(f'Units Sold: {favourite_three_franchises[i]["Units Sold"]} million')
Out:
Units Sold: 400 million

Our new script works because it uses the integer type i to index the list and return one of the franchise dictionaries stored in the list. Once we've got a dictionary type, we can then use the "Name" and "Units Sold" keys to get their values for that franchise.

Cause 3: Using List Values for Indexing

A slightly different cause we can also take a look at is the scenario where we have a list of items we'd like to iterate through to see if a specific value is present. For this example, let's say we have a list of fruit and we'd like to see if orange is in the list. We can easily make the mistake of indexing a list using the list values instead of integers or slices.

fruit_list = ['Apple', 'Grape', 'Orange', 'Peach']

for fruit in fruit_list:
    if fruit_list[fruit] == 'Orange':
        print('Orange is in the list!')
Out:
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-6-0a8aff303bb3> in <module>
      2 
      3 for fruit in fruit_list:
----> 4     if fruit_list[fruit] == 'Orange':
      5         print('Orange is in the list!')
TypeError: list indices must be integers or slices, not str

In this case, we're getting the error because we've used the string values inside the list to index the list. For this example, the solution is pretty simple as we already have the list values stored inside the fruit variable, so there's no need to index the list.

Solution

fruit_list = ['Apple', 'Grape', 'Orange', 'Peach']

for fruit in fruit_list:
    if fruit == 'Orange':
        print('Orange is in the list!')
Out:
Orange is in the list!

As you can see, there was no need for us to index the list in this case; the list values are temporarily stored inside of the fruit variable as the for statement iterates through the list. Because we already have the fruit variable to hand, there's no need to index the list to return it.

For future reference, an easier way of checking if a list contains an item is using an if in statement, like so:

fruit_list = ['Apple', 'Grape', 'Orange', 'Peach']

if 'Orange' in fruit_list:
    print('Orange is in the list!')
Out:
Orange is in the list!

Or if you want the index of an item in the list, use .index():

idx = fruit_list.index('Orange')
print(fruit_list[idx])
Out:
Orange

Bear in mind that using .index() will throw an error if the item doesn't exist in the list.

Summary

This type error occurs when indexing a list with anything other than integers or slices, as the error mentions. Usually, the most straightforward method for solving this problem is to convert any relevant values to integer type using the int() function. Something else to watch out for is accidentally using list values to index a list, which also gives us the type error.


Meet the Authors

alfie-grace-headshot-square.jpg

Alfie graduated with a Master's degree in Mechanical Engineering from University College London. Find him on Upwork, where he is working as a top-rated data scientist.

Brendan Martin
Editor: Brendan Martin
Founder of LearnDataSci

Get updates in your inbox

Join over 7,500 data science learners.