What it is
Python’s enumerate()
wraps any iterable and yields pairs of (index, value). By default the index starts at 0, but you can choose a custom start value.
Why it matters
If you’ve ever written a loop with a manual counter or range(len(...))
, you’ve added noise and opportunities for off-by-one errors. enumerate()
gives you the index and the item in one pass—clearer code, fewer bugs.
How it works / How to use
Basic loop
letters = ["a", "b", "c"]
for i, ch in enumerate(letters):
print(i, ch)
# 0 a
# 1 b
# 2 c
Start counting at 1
for i, ch in enumerate(letters, start=1):
print(i, ch)
# 1 a
# 2 b
# 3 c
It’s an iterator (lazy), not a list
pairs = enumerate(letters)
print(pairs) # <enumerate object at 0x...>
print(list(pairs)) # [(0, 'a'), (1, 'b'), (2, 'c')]
Peek under the hood with next()
pairs = enumerate(["x", "y"], start=10)
print(next(pairs)) # (10, 'x')
print(next(pairs)) # (11, 'y')
# next(pairs) would raise StopIteration
The values arrive one at a time because enumerate()
returns an iterator. You can advance it with the built-in next()
.
Unpacking with dictionaries
months = {"jan": 31, "feb": 28, "mar": 31}
for idx, (name, days) in enumerate(months.items(), start=1):
print(f"{idx}. {name} = {days}")
# 1. jan = 31
# 2. feb = 28
# 3. mar = 31
Use dict.items()
to get key–value pairs, then unpack alongside the index from enumerate()
.
Common patterns
- Skip by index:
if i % 2: continue
- Label output:
print(f"{i+1}) {value}")
when you want 1-based display - Track line numbers while reading files
Limits / Trade‑offs
- Iterator semantics: Once you consume an
enumerate
object, it’s exhausted. Convert to a list first if you need to reuse it. - Not a replacement for every index need: If you’re iterating multiple sequences in lockstep,
zip()
is usually a better fit. - Order comes from the iterable: For mappings, the order reflects the dictionary’s insertion order (Python 3.7+ guarantee).
FAQs
How do I start counting from 1?
Pass start=1
: enumerate(items, start=1)
.
Is enumerate()
more efficient than range(len(...))
?
Yes for readability, and typically equivalent or better for performance because it doesn’t index into the sequence each loop. It also works with any iterable, not just sequences with len
.
Can I get only the indexes?
If you only need positions, use range(len(seq))
for sequences. Otherwise, loop with enumerate()
and ignore the value: for i, _ in enumerate(iterable): ...
What exactly does it return?
An enumerate
object that yields (index, value)
tuples on iteration. You can materialize it with list(enumerate(...))
if needed.
Member discussion