Python enumerate() 활용법
A practical guide to using Python's enumerate() function effectively — from basic iteration to advanced patterns with start parameter and nested loops.
Python enumerate() 활용법
Introduction
enumerate() is one of Python's most underused built-in functions. Many developers still use manual index tracking with range(len()) when enumerate() provides a cleaner, more Pythonic solution. Beyond the basics, enumerate() has features that even experienced developers overlook.
I started using enumerate() more deliberately after reviewing code in a Lisbon trading project. The codebase was full of for i in range(len(data)) patterns that were error-prone and hard to read. Refactoring to use enumerate() improved both readability and reduced index-related bugs.
Environment
Python 3.12.3Problem
The old way — manual index tracking:
data = ["apple", "banana", "cherry", "date"]
# Bad: Manual index tracking
for i in range(len(data)):
print(f"{i}: {data[i]}")
# Bad: Using a counter variable
count = 0
for item in data:
print(f"{count}: {item}")
count += 1Missing the start parameter:
# When you need 1-based indexing
for i, item in enumerate(data):
print(f"{i + 1}. {item}") # Works but verboseNot using enumerate with nested loops:
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
# Manual indexing for nested loops is error-prone
for i in range(len(matrix)):
for j in range(len(matrix[i])):
print(f"matrix[{i}][{j}] = {matrix[i][j]}")Analysis
enumerate() returns an iterator of tuples (index, value). It replaces the pattern of manual index tracking.
Why range(len()) is problematic:
# This can cause IndexError
for i in range(len(data)):
print(data[i]) # What if data changes during iteration?
# This is verbose and harder to read
for i in range(len(data)):
item = data[i]
process(item)Why enumerate() is better:
# Clean and Pythonic
for i, item in enumerate(data):
print(f"{i}: {item}")
# No index out of bounds risk
# No need to access data[i] explicitly
# Works with any iterable, not just sequencesThe start parameter:
# enumerate(iterable, start=0) — default starts at 0
# You can customize the starting indexSolution
Fix 1: Basic enumerate usage
data = ["apple", "banana", "cherry", "date"]
# Clean enumeration
for index, item in enumerate(data):
print(f"{index}: {item}")
# Output:
# 0: apple
# 1: banana
# 2: cherry
# 3: dateFix 2: Use start parameter for 1-based indexing
# Instead of i + 1, use start=1
for index, item in enumerate(data, start=1):
print(f"{index}. {item}")
# Output:
# 1. apple
# 2. banana
# 3. cherry
# 4. dateFix 3: Use with list comprehension
# Create indexed list
indexed = [(i, item) for i, item in enumerate(data)]
# Create dictionary from list
indexed_dict = {i: item for i, item in enumerate(data)}
# Filter with index
even_items = [item for i, item in enumerate(data) if i % 2 == 0]
print(even_items) # ['apple', 'cherry']Fix 4: Use with enumerate for nested loops
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
for i, row in enumerate(matrix):
for j, value in enumerate(row):
print(f"matrix[{i}][{j}] = {value}")Fix 5: Use with zip for parallel iteration
names = ["Alice", "Bob", "Charlie"]
scores = [85, 92, 78]
for i, (name, score) in enumerate(zip(names, scores), start=1):
print(f"{i}. {name}: {score}")
# Output:
# 1. Alice: 85
# 2. Bob: 92
# 3. Charlie: 78Fix 6: Practical patterns
# Pattern 1: Find index of first match
def find_index(predicate, iterable):
for i, item in enumerate(iterable):
if predicate(item):
return i
return -1
index = find_index(lambda x: x > 3, [1, 2, 3, 4, 5])
print(index) # 3
# Pattern 2: Chunked enumeration
def chunked_enumerate(iterable, chunk_size):
for i in range(0, len(iterable), chunk_size):
chunk = iterable[i:i + chunk_size]
yield i // chunk_size, chunk
for chunk_num, chunk in chunked_enumerate(range(20), 5):
print(f"Chunk {chunk_num}: {list(chunk)}")
# Pattern 3: Batch processing with progress
import time
def process_with_progress(items, process_func):
total = len(items)
for i, item in enumerate(items, start=1):
process_func(item)
if i % 100 == 0:
print(f"Processed {i}/{total} ({i/total:.1%})")Lessons Learned
- Always use
enumerate()instead ofrange(len())— it is cleaner and less error-prone. - Use
start=1for human-readable numbering — no morei + 1everywhere. enumerate()works with any iterable — not just lists. It works with generators, file objects, and custom iterables.- Combine
enumerate()withzip()for parallel iteration with indices. - Use enumerate in list comprehensions for building indexed data structures.
This blog does not accept any external sponsorships, affiliate marketing, or ad revenue.