Skip to content

What Is Python’s enumerate() Function and How Do You Use It?

Updated Shivam Malani
What Is Python’s enumerate() Function and How Do You Use It?

What it is

Python’s enumerate() is a built-in that adds a running index to any iterable, yielding pairs of (index, value). It returns a lightweight “enumerate object” you can iterate over directly or cast to a list. See the official documentation for the full signature.

Why it matters

  • Removes error-prone manual counters in loops.
  • Stays readable and “Pythonic” compared to range(len(...)).
  • Works lazily, so it’s efficient for large iterables.

How it works

By default, the index starts at 0. You can change that with the optional start argument.

# Basic usage
runners = ["Lenka", "Martina", "Gugu"]
for i, name in enumerate(runners):
    print(i, name)
# 0 Lenka
# 1 Martina
# 2 Gugu

# One-based indexing
for position, name in enumerate(runners, start=1):
    print(position, name)
# 1 Lenka
# 2 Martina
# 3 Gugu

Under the hood, enumerate() yields a pair on each iteration. You can materialize it to inspect the structure:

seasons = ["Spring", "Summer", "Fall", "Winter"]
print(list(enumerate(seasons)))
# [(0, 'Spring'), (1, 'Summer'), (2, 'Fall'), (3, 'Winter')]

It’s also a regular iterator, so you can step through it with next():

it = enumerate(["a", "b", "c"], start=10)
print(next(it))  # (10, 'a')
print(next(it))  # (11, 'b')
print(next(it))  # (12, 'c')

How to use it (practical patterns)

1) Highlight the first item or a specific step

tasks = ["Pay Rent", "Clean Dishes", "Buy Milk"]
for idx, task in enumerate(tasks):
    if idx == 0:
        print(f"* {task.upper()}!")
    else:
        print(f"* {task}")
# * PAY RENT!
# * Clean Dishes
# * Buy Milk

2) Grab every second character from a string

secret = "3LAigf7eq 5fhiOnpdDs2 Ra6 nwUalyo.9"
message = []
for i, ch in enumerate(secret):
    if i % 2:           # odd indexes only
        message.append(ch)
print("".join(message))

3) Add line numbers while scanning file content

lines = [
    "This is a\tline",
    "This line is fine",
    "Another line with whitespace "
]
for lineno, line in enumerate(lines, start=1):
    if "\t" in line:
        print(f"Line {lineno}: Contains a tab character.")
    if line.rstrip() != line:
        print(f"Line {lineno}: Contains trailing whitespace.")

4) Iterate dictionaries with an index

In modern Python, dicts preserve insertion order, so you can index the pairs consistently:

months = {
    "january": "winter",
    "february": "winter",
    "march": "spring",
}
for idx, (month, season) in enumerate(months.items(), start=1):
    print(f"{idx}: {month} - {season}")
# 1: january - winter
# 2: february - winter
# 3: march - spring

Limits and trade‑offs

  • It’s an iterator, not a list. You can loop it once. If you need random access, cast to list(...) first.
  • It indexes a single iterable. If you’re pairing multiple sequences, zip(...) is a better fit.
  • Avoid range(len(seq)) unless you truly need indexes only. enumerate() communicates both intent and structure more clearly.

When not to use enumerate()

  • Multi-sequence iteration: Prefer zip(a, b) and unpack both values directly.
  • Slicing tasks: If you only need a slice like “first 4 chars,” use slicing, not enumerate() plus conditionals.
  • Adjacent pairs: For routes or consecutive items, reach for tools like itertools.pairwise rather than manual indexing.
# zip() beats enumerate()+index reuse for multi-sequence loops
pets   = ["Leo", "Aubrey", "Frieda"]
owners = ["Bartosz", "Sarah Jane", "Philipp"]
for pet, owner in zip(pets, owners):
    print(f"{pet} & {owner}")

FAQs

What does enumerate() return?
An enumerate object that yields (index, value) tuples as you iterate.

How do I start counting from 1?
Pass start=1 to enumerate(iterable, start=1).

Can I reuse the same enumerate object?
Not after it’s been consumed. It’s an iterator. Create a new one or materialize it as a list if you need multiple passes.

Is enumerate() faster than manual counters?
It’s implemented efficiently and removes bookkeeping from your code. Beyond performance, its clarity is the main win.