Skip to main content

How to Choose between enumerate() and Basic Iteration in Python

Choosing between direct iteration and enumerate() depends on one question: do you need the index of each item?

Basic Iteration for Values Only​

When you only need the items themselves, iterate directly over the collection:

fruits = ["Apple", "Banana", "Cherry"]

for fruit in fruits:
print(fruit)

# Apple
# Banana
# Cherry

This is the cleanest and most Pythonic approach when position doesn't matter.

Using enumerate() for Index and Value​

When you need both the position and the item, enumerate() provides both efficiently:

fruits = ["Apple", "Banana", "Cherry"]

for index, fruit in enumerate(fruits):
print(f"{index}: {fruit}")

# 0: Apple
# 1: Banana
# 2: Cherry

The function returns tuples of (index, item) that you unpack directly in the loop.

Custom Starting Index​

By default, indexing starts at 0. Use the start parameter to change this:

fruits = ["Apple", "Banana", "Cherry"]

# Human-readable ranking starting at 1
for rank, fruit in enumerate(fruits, start=1):
print(f"Rank {rank}: {fruit}")

# Rank 1: Apple
# Rank 2: Banana
# Rank 3: Cherry

This is particularly useful for displaying numbered lists to users.

Avoid the range(len()) Anti-Pattern​

Coming from C or Java, developers often write index-based loops manually:

fruits = ["Apple", "Banana", "Cherry"]

# ❌ Anti-pattern: manual indexing
for i in range(len(fruits)):
print(f"{i}: {fruits[i]}")

# ✅ Pythonic: enumerate
for i, fruit in enumerate(fruits):
print(f"{i}: {fruit}")
warning

The range(len()) pattern is problematic because:

  • It's harder to read
  • Requires repeated indexing into the list
  • Creates opportunities for off-by-one errors
  • Performs slightly worse due to extra index lookups

Practical Use Cases​

Modifying Based on Position​

items = ["first", "second", "third"]
result = []

for i, item in enumerate(items):
if i == 0:
result.append(item.upper())
else:
result.append(item)

print(result) # ['FIRST', 'second', 'third']

Finding Item Positions​

scores = [85, 92, 78, 92, 88]

# Find all positions of highest score
max_score = max(scores)
positions = [i for i, score in enumerate(scores) if score == max_score]

print(f"Max score {max_score} at positions: {positions}")
# Max score 92 at positions: [1, 3]

Processing with Context​

lines = ["Header", "Data 1", "Data 2", "Footer"]

for i, line in enumerate(lines):
if i == 0:
print(f"[HEADER] {line}")
elif i == len(lines) - 1:
print(f"[FOOTER] {line}")
else:
print(f"[DATA] {line}")

Enumerating Other Iterables​

enumerate() works with any iterable, not just lists:

# Strings
for i, char in enumerate("ABC"):
print(f"{i}: {char}")

# Dictionaries (keys)
data = {"a": 1, "b": 2}
for i, key in enumerate(data):
print(f"{i}: {key}")

# Files
with open("data.txt") as f:
for line_num, line in enumerate(f, start=1):
print(f"Line {line_num}: {line.strip()}")
tip

When enumerating files, using start=1 gives you human-readable line numbers that match what text editors display.

Quick Reference​

PatternUse When
for item in iterableYou only need values
for i, item in enumerate(iterable)You need position and value
for i, item in enumerate(iterable, start=1)You need 1-based numbering

Summary​

Use direct iteration (for x in list) when you only need values. Use enumerate() when you need positions. Never manually track indices with i = 0; i += 1 or use range(len()) when iterating over sequences. The enumerate() function is cleaner, less error-prone, and clearly communicates your intent.