enumerate()

Turn a plain iterable into an indexed one — without hand-managing a counter.

Built-in functionPython 2.3+Live demo
Common call
for i, x in enumerate(items):
Returns
iterator of (index, item) — not a list
Replaces
the manual `i = 0; ... i += 1` counter pattern
Watch out
lazy — wrap in list() to materialize
enumerate(iterableiterableAny iterable — list, tuple, generator, string, dict (keys), file.type: iterable · required, startstartFirst index value. Only affects the counter; the items are unchanged.type: int · default: 0=0)
enumerate

Demo

Live evaluation
Try:
Inputs
itemslistcomma-separated items
startintfirst index (empty = 0)
Output
enumerate(['apple', 'pear', 'plum'])
[[0, 'apple'], [1, 'pear'], [2, 'plum']]

enumerate returns an iterator — the demo materializes it as a list of (index, item) pairs so you can see the whole result. In real code you would iterate directly: `for i, x in enumerate(items):`. The start parameter only changes the counter; the items themselves are never modified.

Parameters

NameTypeRequiredDescription
iterableiterableyesAny iterable — list, tuple, generator, string, dict (keys), file.
startintno (0)First index value. Only affects the counter; the items are unchanged.

Return value

enumerateAn iterator of (index, item) tuples. Lazy — nothing is computed until you iterate.

Common patterns

Indexed loop with unpacking
The idiomatic replacement for manual counters.
for i, item in enumerate(items):
    print(i, item)
One-based numbering
Human-readable lists start at 1, not 0.
for i, line in enumerate(lines, start=1):
    print(f"{i}. {line}")
Item → position map
Comprehension over enumerate builds a lookup table in one pass.
positions = {item: i for i, item in enumerate(items)}

Examples

1. Basic indexing
list(enumerate(["a", "b", "c"]))
Returns
[(0, "a"), (1, "b"), (2, "c")]
2. Custom start
list(enumerate(["a", "b"], start=10))
Returns
[(10, "a"), (11, "b")]
3. Over a string
list(enumerate("abc"))
Returns
[(0, "a"), (1, "b"), (2, "c")]
4. Empty is empty
list(enumerate([]))
Returns
[]

Pitfalls

1. Iterator exhausts after one pass
enumerate returns an iterator, not a list. Loop through it twice and the second loop sees nothing.
Empty on reuse
e = enumerate(items)
list(e)  # [(0, "a"), (1, "b")]
list(e)  # []
second list() is empty
Materialize once
pairs = list(enumerate(items))
# reuse pairs freely
reusable list
2. start does not skip items
start changes the counter, not the input. All items still appear.
Misuse
list(enumerate(["a","b","c"], start=2))
[(2, "a"), (3, "b"), (4, "c")]
Actually skip
list(enumerate(["a","b","c"][2:]))
[(0, "c")]
3. Forgetting to unpack the pair
Without unpacking, the loop variable is the whole tuple.
Tuple leak
for x in enumerate(items):
    print(x)
(0, "a"), (1, "b"), ...
Unpack
for i, x in enumerate(items):
    print(i, x)
0 a, 1 b, ...

When to use

Use it
  • Anywhere you need both the item and its index
  • One-based numbering for humans (start=1)
  • Building position lookup tables
  • Iterables without len() — generators, files
Reach for something else
  • Just the items → iterate directly
  • Just indices → range(len(items))
  • Parallel iteration over multiple iterables → zip

Notes

Complexity
O(1) per step
Return
enumerate object (iterator), not list
CPython impl
Python/bltinmodule.c :: enum_next — a tiny generator over the source iterator
Memory
O(1) — one running counter, no buffering
Thread-safe
The counter is safe; the source iterator is only as safe as its type

FAQ

It works, but you then have to index items[i] every step. enumerate gives you both at once, and works on any iterable — including ones without a len (generators, files, network streams).

History

2.3
enumerate() introduced.
2.6
start keyword argument added.