How-To

How-To · Loops

How to Loop With an Index in Python

Loop over a list and get each item's position at the same time using enumerate() — the clean, Pythonic alternative to range(len(...)), including how to start the count at one.

XCODXHow-To · Updated

Overview

You need to loop over a sequence and know *where* you are in it — the index of each item as well as its value. The recommended way in Python is enumerate(): wrap the sequence, and each pass of the loop hands you an (index, item) pair you unpack right in the loop header. It is shorter, clearer and less error-prone than managing a counter yourself.

When do you actually need the index? To number a printed list, to update a slot in place, to report *at what position* a match was found, or to pair each item with a matching entry in another sequence. Whenever the answer is "I need the position too," reach for enumerate() — not a manual counter and not range(len(...)). The steps below show the basic form, how to change the starting number, and why the range(len(...)) habit is worth dropping.

Steps

1. Wrap the sequence in enumerate()

Pass your list to enumerate() and unpack the two values — index first, item second — in the for header. The count starts at 0, matching the item's real position in the sequence.

fruits = ["apple", "pear", "plum"]

for i, fruit in enumerate(fruits):
    print(i, fruit)   # 0 apple, 1 pear, 2 plum

2. Start the count at a custom number

By default the index starts at 0. Pass start= to begin somewhere else — start=1 gives natural "item 1, item 2" numbering for anything a person will read. Only the count shifts; the items and their order stay exactly the same.

fruits = ["apple", "pear", "plum"]

for n, fruit in enumerate(fruits, start=1):
    print(f"{n}. {fruit}")   # 1. apple, 2. pear, 3. plum

3. Don't use range(len(...))

The old-school approach loops over range(len(seq)) and indexes back in with seq[i]. It works, but it is noisier, easier to get wrong, and hides the fact that what you really wanted was the item all along. enumerate() gives you the item directly, so prefer it in every case where you need both position and value.

fruits = ["apple", "pear", "plum"]

# Avoid this:
for i in range(len(fruits)):
    print(i, fruits[i])

# Prefer this:
for i, fruit in enumerate(fruits):
    print(i, fruit)

Runnable example

A complete, runnable example — open it in the Python compiler. It loops over ['a', 'b', 'c'] with enumerate(), so the first printed line is the index and item together:

letters = ['a', 'b', 'c']

for index, letter in enumerate(letters):
    print(index, letter)
# 0 a
# 1 b
# 2 c

Use the index to update items in place

When you need the position to write back into the list, enumerate() gives you the index and the current value together, so you can assign to list[i]:

scores = [70, 82, 91]

for i, s in enumerate(scores):
    scores[i] = s + 5        # bump each score by 5

print(scores)                # [75, 87, 96]

Pair each item with another list by index

A common reason to want the index is to reach into a second, parallel list at the same position:

names = ["Ann", "Bo", "Cy"]
ages  = [30, 25, 41]

for i, name in enumerate(names):
    print(name, "is", ages[i])   # Ann is 30 / Bo is 25 / Cy is 41

For contrast, the manual-counter version below does the same job but you have to declare i, remember to increment it, and place the += 1 where it can't be skipped — three chances to introduce a bug that enumerate() removes:

# Manual counter — verbose and easy to get wrong
i = 0
for fruit in fruits:
    print(i, fruit)
    i += 1        # forget this line and the loop runs forever on the same index

Reach for enumerate() even mid-expression — its pairs feed straight into dict() or a comprehension when you want an index-keyed result:

fruits = ["apple", "pear", "plum"]
by_pos = {i: f for i, f in enumerate(fruits)}
# by_pos -> {0: 'apple', 1: 'pear', 2: 'plum'}
numbered = [f"{i}:{f}" for i, f in enumerate(fruits)]
# numbered -> ['0:apple', '1:pear', '2:plum']

Common pitfalls

One more note: enumerate() returns a lazy iterator, so if you need the pairs more than once, wrap it in list(enumerate(seq)). An enumerate object, like any iterator, is exhausted after a single pass.

Frequently asked questions

How do I get the index of each item in a Python loop?
Use enumerate(): for i, item in enumerate(seq): gives the index and the value together on each pass. The index starts at 0 by default.
How do I make the index start at 1?
Pass the start argument: enumerate(seq, start=1). This shifts only the count, not which items are visited.
Why not use range(len(my_list))?
range(len(...)) forces you to index back in with my_list[i], which is noisier and error-prone. enumerate() hands you the item directly alongside its index, so it reads more clearly.
Can I loop over two lists with an index?
Use enumerate() on one list and index the other, or use zip() to pair items directly. For just position and value from a single sequence, enumerate() is the cleanest choice.