To understand how to fix a TypeError in Python, you first need to know what an iterable object is. An iterable is an object that returns one of its members at a time, allowing it to be iterated over in a for loop. In Python, iterable objects are indexed or placed in data structures such as a string or dictionary using numbers, i.e. integers.
TypeError: String Indices Must Be Integers Explained
When Python raises a TypeError: string indices must be integers, it’s often because values at index are attempted to be extracted using string value instead of the integer index.
When values at index are extracted using string value, an incorrect type of input, it raises an error like this:
TypeError: string indices must be integers
This article will explore when and how that error occurs, and how to resolve it by understanding the anatomy of certain data structures via different scenarios. Each problem instance will be understood in depth, the meaning will be interpreted and eventually will be solved.
What Causes a TypeError in Python?
When you start coding, receiving a TypeError is one of the most annoying things you can experience as a programmer. It seems like the world has come to an end and one might never master the art of coding. But don’t give up.
To begin with, one must know the anatomy of the problem in order to solve it. Here, the problem occurs due to an incompatibility of the argument we passed through our data structure. Let’s understand how and when an error can occur through a couple of illustrations.
1. String Index vs. Integer Index
Suppose we have a string as shown below. Since Python is a dynamically typed language, i.e. the type of variable is checked during the run-time, we don’t need to mention keywords like int
, str
or char
before the variable used. We try to index a part of the string, which is a way to refer to an individual item within an iterable (string) by its position. In Python, objects are zero-indexed, i.e. the position count starts at zero. Now, if you want to access the letter ‘e’ from the string, you may follow the given approach:
In [1]: string="typeerror"
In [2]: string['e']
Traceback (most recent call last):
File "<ipython-input-8-1b9006e9beb0>", line 1, in <module>
string['e']
TypeError: string indices must be integers
The error is self-explanatory, but let’s read what the message is trying to say. Python is an interpreted language, which means it will stop compiling the program as soon as a syntax error exists and will not run again until the problem is solved. Now, it might confuse you that the error is on the second line, but it says “line 1.” In the environment I used, which is Spyder and a part of a Python distribution, Anaconda, the first line is called line 0. Thus, at line 1, it displays type error which denotes that the value of the indices provided is of another type. We are trying to extract a value from a string using string index instead of integer index. Look at the following infographic to understand what exactly a string looks like and how the items are indexed in the iterable:
2. String Indices Must Be Integers, Not Tuples
Another way to extract a part of text from string is via slicing. Slicing is a technique of getting a subset of elements, i.e. a small list based on the index value of the iterable (list). It has prominent applications in tasks like optimization, error analysis, debugging, flow control and many more. Let’s go through an example:
In [3]: mystring="gratitude"
In [4]: mystring[0,5]
Traceback (most recent call last):
File "<ipython-input-13-7c2881597196>", line 1, in <module>
mystring[0,5]
TypeError: string indices must be integers
Why did we receive the error? While we’ve used integer indexes to slice the iterable, it shows the same error of compatibility issue. To be honest, it’s an incorrect explanation to the mistake we have made. We need to dig a little deeper, so we will save the integer index in another string object and then look up the type of the same.
In [5]: extract=0,5
In [6]: type(extract)
Out[6]: tuple
Because it is a tuple, which is one of the built-in data types in Python other than list, set and dictionary, it did not show the output we expected. The comma ,
in the string is automatically evaluated as tuple and makes the error misleading. Therefore, the error should have been something like this:
In [7]: mystring[extract]
Traceback (most recent call last):
File "<ipython-input-16-308e1ed6160d>", line 1, in <module>mystring[extract]
TypeError: string indices must be integers(not tuple)
3. Accessing Values Using String Index instead of Integer Index
The next data structure is a dictionary, and it is slightly more complex than a list. Thus, we must know how it’s structured:
Dictionary={
key1 : value1,
key2 : value2,
.
.
keyN : valueN,
}
A key could be any entity like name, address, gender and phone, while values are the attributes like “Max” for name. One key can even have multiple values separated by commas and be double or single-quoted.
Let us create a dictionary called “phone_book
,” with keys Name
, Mobile
, and Address
, however, we will use a simpler dictionary for better understanding.
In [8]: phone_book={
"Name": "Jennifer Aniston",
"Phone": “1800”,
"Address": "Apt20”
}
In order to iterate over all the values in the dictionary and print them, we will use the following code snippet, where k
is for all the keys residing in the dictionary:
In [9]: for k in phone_book:
...: print("Name:" + k["Name"])
...: print("Phone:" + k["Phone"])
...: print("Address:" + k["Address"])
Traceback (most recent call last):
File "<ipython-input-20-e5c1b8f425c3>", line 2, in <module>
print("Name:" + k["Name"])
TypeError: string indices must be integers
The error is present because we are trying to access values using string index instead of the integer index. However, that’s not all that it’s shown and will elucidate further in the solutions section.
How to Solve TypeError in Python
1. String Index vs. Integer Index: Solution
Since we were using string index, we received a type error because values are stored at an address starting from 0 in both string and dictionary. Now we will try to index the string “typeerror
” using the integer, as that is the correct way to extract information.
In [10]: string[0]
Out[10]: 't'
Voila. It displayed what we were looking for. Try it yourself to extract items at different locations of iterable by passing values from zero to eight.Wondering why and how eight? As we saw in the above infographic, it had nine letters, and the numbering started from zero and the last one is eight. But what if the string is longer and we don’t have much time to count each letter and space (yes, a space counts). You can do the following to get the size of the string:
In [11]: string1 = “Hi there”
In [12]: len(string1)
Out[12]: 7
2. String Indices Must Be Integers, Not Tuples: Solution
Since we were slicing the string using a comma, we received a type error because Python evaluates commas ,
as Tuple. Thus, we replace that with a colon ‘:
’. Follow the code below:
In [13]: mystring[0:5]
Out[13]: 'grati'
3. Accessing Values Using String Index instead of Integer Index: Solution
In dictionary, we tried to access the values using k
and passing the keys to it, but the problem is in the for loop as you can see below:
k
is a key,- Key is
Name
in the dictionaryphone_book
and - We pass
Name
toName
to get the value.
We can’t use one string to access another string. Confused, right? It’s like opening a lock using a lock. The following code will make it clearer.
In [14]: for k in phone_book:
...: print(k)
...:
Name
Phone
Address
Here, we tried to access the key’s value, dict[key:value]
, by passing the key name itself. But the way to do it is to pass the index or position of the item in an object like string, and for a dictionary, the name of the dictionary needs to be mentioned to retrieve them. Thus, we must use the dictionary name instead of k
as the dictionary key can be strings. Thus, follow the below method:
In [15]: phone_book={
...: "Name": "Jennifer Aniston",
...: "Phone": "1800",
...: "Address": "Apt20",
...: }
In [16]: print("Name:" + phone_book["Name"])
...: print("Phone:" + phone_book["Phone"])
...: print("Address:" + phone_book["Address"])
Name:Jennifer Aniston
Phone:1800
Address:Apt20
Our code ran successfully. Once we diagnosed the cause of the problem, it became clearer and easier to solve it. The wrong argument passed to search the available content in the iterable, strings and dictionaries, raised the error. Following that, we made changes accordingly, and therefore, we were able to get the expected output, i.e. the item/alphabet at the mentioned location of the string and the details of the dictionary with key and its value.
The lessons from each of these scenarios is that:
- String indices must be an integer (
string[0]
). - Slicing is done through colon
:
(string[0:1]
), not commas,
as Python thinks it’s a tuple. - Moreover, dictionary items must be accessed only using a dictionary name, not a key in the dictionary.
There you go. Now, you can solve this error and work like a pro.
Frequently Asked Questions
What are string indices?
String indices in Python refer to the index values of characters in a string. Each string character in Python has an associated index value, with the first character having an index of 0 and ascending accordingly.
How to resolve string indices must be integers?
To fix TypeError: string indices must be integers
in Python, make sure of the following:
- When getting the index of a string character: Only use integers to get a string index (like
string[0]
, instead ofstring[‘a’]
). - When slicing a string using indices: Only use a colon to specify the slice length (like
string[0:1]
, instead ofstring[0,1]
). - When getting key values in a dictionary: Use the name of dictionary itself when iterating.