Iterating with enumerate() is one of Python’s most useful and frequently used iteration tools — it lets you loop over any iterable while automatically getting both the element and its index (position) at the same time. Instead of manually managing a counter variable, enumerate() pairs each item with a number — starting at 0 by default, or any value you choose with start=. This makes it perfect for numbered lists, tracking positions, building indexed data, or when order matters in processing.
In 2026, enumerate() remains a core Pythonic pattern — used everywhere from simple lists to pandas DataFrames, file line numbering, and custom indexing. Here’s a complete, practical guide to using enumerate(): how it works, real-world patterns, and modern best practices with type hints and clarity.
The basic form is simple: for index, item in enumerate(iterable): — the loop variable unpacks each pair automatically. By default, counting starts at 0, but you can change it with start=.
fruits = ["apple", "banana", "cherry", "date"]
for index, fruit in enumerate(fruits):
print(f"Position {index}: {fruit}")
# Output:
# Position 0: apple
# Position 1: banana
# Position 2: cherry
# Position 3: date
Change the starting number with start= — very common for 1-based lists, reports, or user-facing numbering.
for index, fruit in enumerate(fruits, start=1):
print(f"{index}. {fruit}")
# Output:
# 1. apple
# 2. banana
# 3. cherry
# 4. date
Real-world pattern: processing numbered lines from a file — enumerate() gives line numbers automatically, great for logging, debugging, or reporting errors with context.
with open("log.txt", "r", encoding="utf-8") as f:
for line_num, line in enumerate(f, start=1):
clean_line = line.strip()
if "ERROR" in clean_line.upper():
print(f"Error found on line {line_num}: {clean_line}")
Another everyday use: building indexed data structures — like lists of tuples, dictionaries with positions, or filtering with index conditions.
scores = [85, 92, 78, 95, 88]
# Find positions of high scores (>90)
high_scores = [(i, score) for i, score in enumerate(scores, start=1) if score > 90]
print(high_scores) # [(2, 92), (4, 95)]
# Create numbered dictionary
numbered_fruits = {i: fruit for i, fruit in enumerate(fruits, start=1)}
print(numbered_fruits) # {1: 'apple', 2: 'banana', 3: 'cherry', 4: 'date'}
Best practices make enumerate() iteration clean, safe, and efficient. Prefer unpacking into two variables (index, item) — it’s more readable than using item[0] or item[1]. Use start=1 for user-facing or report-style numbering — 0-based is fine for internal code. Avoid modifying the iterable inside the loop — it can skip items or raise errors; collect changes in a new list instead. Combine with zip() when iterating multiple iterables — e.g. for i, (a, b) in enumerate(zip(list1, list2), start=1). Modern tip: use type hints for clarity — for i: int, item: str in enumerate(...) — improves IDE support and mypy checks. In production, when iterating over external data (files, APIs), wrap in try/except — handle bad lines or empty iterables gracefully without crashing the loop.
enumerate() turns basic iteration into numbered, position-aware processing — clean, safe, and Pythonic. In 2026, use it with start= for readable numbering, unpacking for clarity, and type hints for safety. Master enumerate(), and you’ll handle lists, files, DataFrames, and sequences with confidence and elegance.
Next time you need both items and their positions — reach for enumerate(). It’s Python’s cleanest way to say: “Give me every element and tell me where it is.”