# Finding the index of an item in a list

Reference: Data Structures > More on Lists

# Caveats follow

Note that while this is perhaps the cleanest way to answer the question as asked`index` is a rather weak component of the `list` API, and I can’t remember the last time I used it in anger. It’s been pointed out to me in the comments that because this answer is heavily referenced, it should be made more complete. Some caveats about `list.index` follow. It is probably worth initially taking a look at the documentation for it:

```list.index(x[, start[, end]])
```

Return zero-based index in the list of the first item whose value is equal to x. Raises a `ValueError` if there is no such item.

The optional arguments start and end are interpreted as in the slice notation and are used to limit the search to a particular subsequence of the list. The returned index is computed relative to the beginning of the full sequence rather than the start argument.

## Linear time-complexity in list length

An `index` call checks every element of the list in order, until it finds a match. If your list is long, and you don’t know roughly where in the list it occurs, this search could become a bottleneck. In that case, you should consider a different data structure. Note that if you know roughly where to find the match, you can give `index` a hint. For instance, in this snippet, `l.index(999_999, 999_990, 1_000_000)` is roughly five orders of magnitude faster than straight `l.index(999_999)`, because the former only has to search 10 entries, while the latter searches a million:

```>>> import timeit
>>> timeit.timeit('l.index(999_999)', setup='l = list(range(0, 1_000_000))', number=1000)
9.356267921015387
>>> timeit.timeit('l.index(999_999, 999_990, 1_000_000)', setup='l = list(range(0, 1_000_000))', number=1000)
0.0004404920036904514

```

## Only returns the index of the first match to its argument

A call to `index` searches through the list in order until it finds a match, and stops there. If you expect to need indices of more matches, you should use a list comprehension, or generator expression.

```>>> [1, 1].index(1)
0
>>> [i for i, e in enumerate([1, 2, 1]) if e == 1]
[0, 2]
>>> g = (i for i, e in enumerate([1, 2, 1]) if e == 1)
>>> next(g)
0
>>> next(g)
2
```

Most places where I once would have used `index`, I now use a list comprehension or generator expression because they’re more generalizable. So if you’re considering reaching for `index`, take a look at these excellent Python features.

## Throws if element not present in list

A call to `index` results in a `ValueError` if the item’s not present.

```>>> [1, 1].index(2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: 2 is not in list
```

If the item might not be present in the list, you should either

1. Check for it first with `item in my_list` (clean, readable approach), or
2. Wrap the `index` call in a `try/except` block which catches `ValueError` (probably faster, at least when the list to search is long, and the item is usually present.)