This tutorial shows you everything you need to know to help you master the essential index()
method of the most fundamental container data type in the Python programming language.
Definition and Usage: The list.index(value)
method returns the index of the value
argument in the list
. You can use optional start
and stop
arguments to limit the index range where to search for the value in the list. If the value is not in the list, the method throws a ValueError
.
Here’s a short example:
>>> lst = ["Alice", 42, "Bob", 99] >>> lst.index("Alice") 0 >>> lst.index(99) 3 >>> lst.index(99, 1, 3) Traceback (most recent call last): File "<pyshell#9>", line 1, in <module> lst.index(99, 1, 3) ValueError: 99 is not in list
In the first line of the example, you create the list lst
. You then look up the index of the elements "Alice"
and 99
. If you use start=1
and stop=3
, the value 99
is not found anymore and Python throws a ValueError
.
Code Puzzle — Try It Yourself:
Now you know the basics. Let’s deepen your understanding with a short code puzzle—can you solve it?
# Create a list of customers customers = ['Alice', 'Bob', 'Frank', 'Ann'] # Extract all names of customers starting with 'A' indices_of_A = [customers.index(x) for x in customers if x[0] == 'A'] # Print the resulting customers print(list(customers[i] for i in indices_of_A)) # What's the output of this puzzle?
You can also solve this puzzle and track your Python skills on our interactive Finxter app.
Syntax: You can call this method on each list object in Python (Python versions 2.x and 3.x). Here’s the syntax:
list.index(value, start=0, stop=9223372036854775807)
Arguments:
Argument | Description |
---|---|
value | Returns the index of value in the list . A value appears in the list if the == operator returns True . If the value doesn’t exist in the list, the return value is -1 . |
start | (Optional.) The index of where you want to start searching in the list. All list elements in front of this position are ignored. This is a positional argument, not a keyword argument. |
stop | (Optional.) The index of where you want to stop searching in the list. All list elements after this position are ignored. This is a positional argument, not a keyword argument. |
Return value: The method list.index(value)
returns an integer value representing the index where the argument value
appears in the list. If the value does not appear in the list, the method throws a ValueError
.
Related articles:
Here’s your free PDF cheat sheet showing you all Python list methods on one simple page. Click the image to download the high-resolution PDF file, print it, and post it to your office wall:
Python List Index Implementation
So you really want to know the cPython implementation of the index()
method?
On a high level, the algorithm to find the index of a given value in the list consists of the following steps:
- Ensure that the start and stop indices are at least zero.
- Iterate over all elements in the list and check if they are equal.
- If they are equal, return immediately from the method.
- If no element is found, throw the
ValueError
.
Here’s the C++ implementation in case you want to revive your C++ skills a bit. Otherwise, just skip it and move immediately to the next section where I’ll discuss the computational complexity of the algorithm.
/*[clinic input] list.index value: object start: slice_index(accept={int}) = 0 stop: slice_index(accept={int}, c_default="PY_SSIZE_T_MAX") = sys.maxsize / Return first index of value. Raises ValueError if the value is not present. [clinic start generated code]*/ static PyObject * list_index_impl(PyListObject *self, PyObject *value, Py_ssize_t start, Py_ssize_t stop) /*[clinic end generated code: output=ec51b88787e4e481 input=40ec5826303a0eb1]*/ { Py_ssize_t i; if (start < 0) { start += Py_SIZE(self); if (start < 0) start = 0; } if (stop < 0) { stop += Py_SIZE(self); if (stop < 0) stop = 0; } for (i = start; i < stop && i < Py_SIZE(self); i++) { PyObject *obj = self->ob_item[i]; Py_INCREF(obj); int cmp = PyObject_RichCompareBool(obj, value, Py_EQ); Py_DECREF(obj); if (cmp > 0) return PyLong_FromSsize_t(i); else if (cmp < 0) return NULL; } PyErr_Format(PyExc_ValueError, "%R is not in list", value); return NULL; }
But what’s the computational complexity of this index()
method in Python?
Python List Index Time Complexity
For simplicity, here’s the Python equivalent of the implementation with some basic simplifications that don’t change the overall complexity:
def index(value, lst): for i, el in enumerate(lst): if el==value: return i raise Exception('ValueError') print(index(42, [1, 2, 42, 99])) # 2 print(index("Alice", [1, 2, 3])) ''' Traceback (most recent call last): File "C:\Users\xcent\Desktop\code.py", line 10, in <module> print(index("Alice", [1, 2, 3])) File "C:\Users\xcent\Desktop\code.py", line 5, in index raise Exception('ValueError') Exception: ValueError '''
I know it’s not the perfect replication of the above C++ code. But it’s enough to see the computational (runtime) complexity of the list.index(value)
method.
The index()
method has linear runtime complexity in the number of list elements. For n
elements, the runtime complexity is O(n)
because in the worst-case you need to iterate over each element in the list to find that the element does not appear in it.
Let’s check the runtime complexity practically for different list sizes with a short benchmark program.
You can see a plot of the time complexity of the index()
method for growing list size here:
The figure shows how the elapsed time of finding the last list element in a list. This experiment is repeated for growing number of elements. The runtime grows linear to the number of elements.
If you’re interested in the code I used to generate this plot with Matplotlib, this is it:
import matplotlib.pyplot as plt import time y = [] for i in [100000 * j for j in range(10,100)]: lst = list(range(i)) t0 = time.time() x = lst.count(-99) t1 = time.time() y.append(t1-t0) plt.plot(y) plt.xlabel("List elements (10**5)") plt.ylabel("Time (sec)") plt.show()
Related articles:
Python List Index Without Exception
Per default, the list.index()
method will throw a ValueError
if the value is not equal to an element of the list
. When I first encountered the list.index() method, I assumed that the return value will be simply -1 so I was surprised that the method threw an error. However, after thinking about the problem, I came to the conclusion that it makes a lot of sense NOT to return the value -1 if an index cannot be found. The reason is that by convention, the index -1 refers to the last element in the list in Python:
>>> lst = [1, 2, 3] >>> lst[-1] 3
But what if you don’t want to get an exception if the value cannot be found?
In this case, you can use lambda functions and list comprehension to write your own small method in a single line of code:
>>> ind = lambda l, v: [i for i in range(len(l)) if l[i] == v] >>> ind('Alice', ['Bob', 'Alice', 'Frank']) [] >>> ind(['Bob', 'Alice', 'Frank'], 'Alice') [1]
The function ind
finds all occurrences of a given value in a given list in linear runtime without throwing an error. Instead, it’ll simply return an empty list.
Related Articles
- List Comprehension (Internal Link to Finxter Blog)
- Lambda Function (Internal Link to Finxter Blog)
- Python One-Liner Book (External Link to Amazon)
Python List Index Try Catch
The Python list.index(value)
method throws a ValueError
if the value is not in the list. If you’re not doing anything about it, this can break your whole program. So what can you do about it?
The Pythonic way is to “catch” the exception in a try/catch block. You can then handle it in the catch block that’s only executed if the value is not in the list. (You need a backup plan anyways.)
Here’s how you can catch the ValueError
in a minimal code snippet:
lst = [1, 2, 3] try: index = lst.index('Alice') except ValueError: index = None print(index) # None
The output is the expected:
None
You don’t even see that there was an exception when executing the code.
However, if this seems to long-winded for you (and you love Python one-liners as much as I do, you should do the following:
First, check out my new book Python One-Liners that will teach you to understand every single line of code you’ll ever encounter in practice.
Second, use a one-liner to achieve the same thing:
lst = [1, 2, 3] indices = [i for i in range(len(lst)) if lst[i]=='Alice'] index = indices[0] if indices else None print(index)
This is my preferred option.
Python List Index Out of Range
This error message appears if you try to access list elements with an index that’s either larger than the maximal allowed index or smaller than the negative indexing -len(list)
.
Here’s the minimal example of both cases:
>>> lst = [1, 2, 3] >>> lst[3] Traceback (most recent call last): File "<pyshell#3>", line 1, in <module> lst[3] IndexError: list index out of range >>> lst[-5] Traceback (most recent call last): File "<pyshell#4>", line 1, in <module> lst[-5] IndexError: list index out of range
To avoid the IndexError, just use indices within the allowed range (inclusive numbers) between -len(list)
and +len(list)-1
.
Here’s how this error can appear when removing elements from a list while iterating over it:
l=[3, 3, 3, 4, 4, 4] for i in range(0,len(l)): l.pop(i) Traceback (most recent call last): File "C:\Users\xcent\Desktop\code.py", line 3, in <module> l.pop(i) IndexError: pop index out of range
Don’t do that! The behavior won’t be as you expected because the iterator is created only once before entering the loop. But removing an element from a list can change the indices of all elements in the list so the predefined indices do not point to the correct elements anymore.
Python List Index Multiple
To find multiple elements of an element in the list, you can use the index()
method multiple times by setting the start index to the previously found index.
lst = [1, 2, 3, 3, 3, 3, 3, 3, 0, 0, 0] value = 3 min_index = 0 indices = [] while min_index < len(lst): try: indices.append(lst.index(value, min_index)) min_index = indices[-1] + 1 except ValueError: min_index = len(lst) print(indices) # [2, 3, 4, 5, 6, 7]
But I wouldn’t advise it as it’s complicated and hard to read. A simple one-liner is all you need:
indices = [i for i in range(len(lst)) if lst[i] == value] print(indices) # [2, 3, 4, 5, 6, 7]
Beautiful is better than complex!
Python List Index of Max / Min
Given is a list:
a = [33, 11, 23, 55, 89, 101, 1, 101, 33, 83, 101]
The maximum element in the list is 101.
Problem: find all index position(s) of the maximum in the list.
Solution: use the following concise solution to get a list of maximum positions.
a = [33, 11, 23, 55, 89, 101, 1, 101, 33, 83, 101] maxs = [i for i in range(len(a)) if a[i] == max(a)] print(maxs) # [5, 7, 10]
In the code snippet, you use list comprehension to get all indices of the maximum element max(a)
.
Of course, if you care about performance, you can also optimize this by calculating max(a)
once, store it in a variable max_a
and using the variable in instead of calculating it again and again.
a = [33, 11, 23, 55, 89, 101, 1, 101, 33, 83, 101] max_a = max(a) maxs = [i for i in range(len(a)) if a[i] == max_a] print(maxs) # [5, 7, 10]
You can easily do the same thing for the indices of the minimum elements in a list by using min(a) rather than max(a):
a = [33, 11, 23, 55, 89, 101, 1, 101, 33, 83, 101] min_a = min(a) mins = [i for i in range(len(a)) if a[i] == min_a] print(mins) # [6]
Python List Index From End (Reverse)
You can calculate the index from the end by using the reversed list (I used slicing lst[::-1]
with negative step size to reverse the list).
Say, you’ve a list of elements. You’re looking for the value 101. By default, the list.index(value) method looks from the left and returns the left-most element that’s equal to value. But what if you want to do this from the right?
Here’s how: you calculate the index (with respect to the original list) like this: index_right = len(a) - a[::-1].index(101) - 1
.
a = [23, 55, 89, 101, 1, 101, 33, 83] index_left = a.index(101) index_right = len(a) - a[::-1].index(101) - 1 print(index_left) # 3 print(index_right) # 5
Just think about it for a moment. If you just reverse the list and search for the first occurrence of the value, you’ll get the wrong index with regards to the original list. (You’ll get it backwards.) So you first need to reverse the indexing scheme as done in the code.
Python List Index Regex / Wildcard
How can you find the index of the elements in a list that match a certain regex?
Related article:
Answer: You do this with a short list comprehension statement (there’s no built-in method and it’s simple enough).
import re lst = ['Alice', 'Bob', 'Ann', 'Albrecht'] pattern = 'A.*' matching_indices = [i for i in range(len(lst)) if re.match(pattern, lst[i])] print(matching_indices) # [0, 2, 3]
The re.match(pattern, lst[i])
method returns a matching object if the pattern matches the element at position i in the list. In this case, you add it to the result list.
Python List Index Tuple
How to find an index of a tuple in a list of tuples?
Use the list.index(value)
method that returns the index of the first occurrence of the value in the list. It also works for tuples:
>>> [(1, 1), (2, 2), (3, 3)].index((3,3)) 2
Python List Index True False
How to find all indices of True
values in a list of tuples?
Use list comprehension with the built-in enumerate()
function to iterate over all (index, value) pairs. Here’s the minimal example:
lst = [True, True, True, False, False, True] print([i for i, x in enumerate(lst) if x]) # [0, 1, 2, 5]
You can do the same but check for not x
to find all indices of False
values in a list:
lst = [True, True, True, False, False, True] print([i for i, x in enumerate(lst) if not x]) # [3, 4]
Python List Index Zero / Non-Zero
How to find the indices of all zero elements in a list?
Use list comprehension with the built-in enumerate()
function to iterate over all (index, value) pairs. Here’s the minimal example:
lst = [0, 0, 0, 1, 1, 1, 0, 1] print([i for i, x in enumerate(lst) if not x]) # [0, 1, 2, 6]
You can find all non-zero elements by skipping the negation in the list comprehension condition:
lst = [0, 0, 0, 1, 1, 1, 0, 1] print([i for i, x in enumerate(lst) if x]) # [3, 4, 5, 7]
Python List Index Pop
The list.pop(index)
method with the optional argument index removes and returns the element at the position index.
Related article:
An example is as follows:
>>> lst = [1, 2, 3] >>> lst.pop() 3 >>> lst [1, 2]
In the first line of the example, you create the list lst
. You then remove and return the final element 3 from the list. The result is the list with only two elements [1, 2]
.
Python List Index Delete
This trick is also relatively unknown among Python beginners:
- Use
del lst[index]
to remove the element at index. - Use
del lst[start:stop]
to remove all elements in the slice.
>>> lst = list(range(10)) >>> lst [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> del lst[5] >>> lst [0, 1, 2, 3, 4, 6, 7, 8, 9] >>> del lst[:4] >>> lst [4, 6, 7, 8, 9]
Python List Index Range
If you’re looking for an index range, you’re probably meaning slicing which is an advanced technique to carve out a range of values from a Python list or string. See the full slicing tutorial on the Finxter blog here.
The notation is list[start:stop:step]
. The step argument is optional and you don’t need it to carve out a range of values.
Here are some examples:
>>> lst = ['a', 'b', 'c', 'd', 'e'] >>> lst[:] ['a', 'b', 'c', 'd', 'e'] >>> lst[2:4] ['c', 'd'] >>> lst[3:] ['d', 'e'] >>> lst[:-3] ['a', 'b'] >>> lst[:-1] ['a', 'b', 'c', 'd'] >>> lst[::2] ['a', 'c', 'e']
Python List Index on 2D Lists
Say, you want to search the row and column index of the value 5 in the array
a = [[1, 2], [3, 4], [5, 6]]
You can simply calculate the x and y coordinates like this:
a = [[1, 2], [3, 4], [5, 6]] row = [x for x in a if 5 in x][0] x = a.index(row) y = row.index(5) print(x, y) # 2 0
Python List index() Thread Safe
Do you have multiple threads that access your list at the same time? Then you need to be sure that the list operations (such as index()
) are actually thread safe.
In other words: can you call the
operation in two threads on the same list at the same time? (And can you be sure that the result is meaningful?)index
()
The answer is yes (if you use the cPython implementation). The reason is Python’s global interpreter lock that ensures that a thread that’s currently working on its code will first finish its current basic Python operation as defined by the cPython implementation. Only if it terminates with this operation will the next thread be able to access the computational resource. This is ensured with a sophisticated locking scheme by the cPython implementation.
The only thing you need to know is that each basic operation in the cPython implementation is atomic. It’s executed wholly and at once before any other thread has the chance to run on the same virtual engine. Therefore, there are no race conditions. An example of such a race condition would be the following: the first thread reads a value from the list, the second thread overwrites the value, and the first thread overwrites the value again invalidating the second thread’s operation.
All cPython operations are thread-safe. But if you combine those operations into higher-level functions, those are not generally thread safe as they consist of many (possibly interleaving) operations.
Where to Go From Here?
The list.index(value)
method finds the index of the first occurrence of the element value
in the list
. You’ve learned the ins and outs of this important Python list method.
If you keep struggling with those basic Python commands and you feel stuck in your learning progress, I’ve got something for you: Python One-Liners (Amazon Link).
In the book, I’ll give you a thorough overview of critical computer science topics such as machine learning, regular expression, data science, NumPy, and Python basics—all in a single line of Python code!
OFFICIAL BOOK DESCRIPTION: Python One-Liners will show readers how to perform useful tasks with one line of Python code. Following a brief Python refresher, the book covers essential advanced topics like slicing, list comprehension, broadcasting, lambda functions, algorithms, regular expressions, neural networks, logistic regression and more. Each of the 50 book sections introduces a problem to solve, walks the reader through the skills necessary to solve that problem, then provides a concise one-liner Python solution with a detailed explanation.