概要
Pythonの for
ループで配列やリストを扱うとき、
要素とインデックスを同時に扱いたいというケースは非常に多い。
enumerate()
はそのニーズに対して、最小限の記述で最大限の意図を表現するPython的手法である。
本稿では enumerate()
の基本から、意図の明示性・安全性・応用性までを掘り下げる。
1. 基本構文と挙動
names = ["Alice", "Bob", "Charlie"]
for index, name in enumerate(names):
print(index, name)
出力:
0 Alice
1 Bob
2 Charlie
-
enumerate(iterable)
は(index, item)
のタプルを返すイテレータ - デフォルトでは
0
からカウントされる
2. スタート値の指定も可能
for i, name in enumerate(names, start=1):
print(f"{i}. {name}")
→ 出力:
1. Alice
2. Bob
3. Charlie
→ UI出力や人間向け番号に最適
3. 比較:非Pythonicな書き方
for i in range(len(names)):
print(i, names[i])
- 冗長、エラーに弱い(
IndexError
の可能性) - 可読性に乏しく、“意図より手段が前面に出てしまう”
4. リスト内包表記・辞書作成への応用
# インデックス付きの辞書を作る
d = {i: name for i, name in enumerate(names)}
# → {0: 'Alice', 1: 'Bob', 2: 'Charlie'}
# 偶数インデックスだけを抽出
even_indexed = [name for i, name in enumerate(names) if i % 2 == 0]
5. ネスト構造との併用
matrix = [[1, 2], [3, 4], [5, 6]]
for row_idx, row in enumerate(matrix):
for col_idx, value in enumerate(row):
print(f"{row_idx},{col_idx} = {value}")
→ 多次元構造でも自然にインデックス追跡が可能
6. zipとの併用で柔軟な構造構築
labels = ["A", "B", "C"]
values = [10, 20, 30]
for i, (label, value) in enumerate(zip(labels, values), start=1):
print(f"{i}: {label} → {value}")
→ 複数リストを番号付きで結合出力したいときに強力
よくある誤解と対策
❌ enumerate()
はrangeより遅い?
→ ✅ 理論上はイテレータ生成が入るが、実用上の差は無視できる
→ むしろ安全性・可読性を損なうrangeは避けるべき
❌ インデックスが不要ならenumerateは過剰?
→ ✅ インデックスを使わないなら for item in iterable:
でよい
→ 使う場面が明確であれば、enumerateは最適解
❌ ネストループには使いづらい?
→ ✅ 問題なし。むしろ明示的なインデックス変数管理が不要になる
結語
enumerate()
は、Pythonの設計思想である
“明示性と簡潔さの両立” を体現するイテレーション手法である。
- rangeやインデックス管理のノイズを排除し
- 開発者の意図をコード構造に直結させ
- リスト・辞書・多次元構造にまで拡張可能
Pythonicとは、制御ではなく意図を記述するアプローチであり、
enumerate()
はその静かな代表例である。