Python はインデックスと値のペアを列挙します

Python enumerate は実行インデックスを反復可能に追加し、ループ中に (index, value) ペアを返します。 番号付き出力やラベルなど、各項目の位置が必要な場合に使用します。 これは、各項目をリスト、ジェネレーター、またはファイル行全体での位置と組み合わせるための組み込みパターンです。

番号付き出力の Python 列挙例

出力:

ここに出力が表示されます...

出力:

1. ship order
2. email customer

この例の仕組み

  1. enumerate(tasks, start=1) は、各タスクとその位置を組み合わせます。
  2. start=1 は数値を人間に優しいものにします。
  3. 出力には、番号が付けられた各タスクが表示されます。

Python enumerate でよくある落とし穴

間違い 1: 番号が 0 から始まることを忘れています。

for line_no, row in enumerate(rows):
    print(f"Line {line_no}: {row['sku']}")
for line_no, row in enumerate(rows, start=1):
    print(f"Line {line_no}: {row['sku']}")

この問題が発生する理由: enumerate のデフォルトは 0 です。これは、ゼロベースのインデックスには正しいですが、人間が目にする行番号には混乱を招きます。

間違い 2: 辞書を列挙して値を期待しています。

region_totals = {"west": 1200, "east": 980}
for i, total in enumerate(region_totals):
    print(i, total)
region_totals = {"west": 1200, "east": 980}
for i, (region, total) in enumerate(region_totals.items(), start=1):
    print(i, region, total)

これが起こる理由: dict を反復するとキーが生成されるため、.items() をループしない限り、enumerate はインデックスとキーをペアにします。 キー/値の検索パターンが必要な場合は、Python dict の例 を参照してください。

間違い 3: 大きなデータ用に list(enumerate(...)) を構築する。

indexed_rows = list(enumerate(rows, start=1))
for line_no, row in indexed_rows:
    print(line_no, row)
for line_no, row in enumerate(rows, start=1):
    print(line_no, row)

これが起こる理由: list() はすべてのペアを強制的にメモリに格納しますが、enumerate はすでに遅延しており、行をストリーミングできます。

enumerate と range(len()): どちらを使用するか

次の場合には enumerate を使用してください…次の場合には range(len()) を使用してください…
インデックスと項目が一緒に必要です。必要なのは数値インデックスのみです。
ジェネレーターを含むあらゆる反復可能オブジェクトを反復しています。カスタム ステップでジャンプするか、インデックスのみで反復する必要があります。
手動インデックスを作成せずに読み取り可能なループが必要です。スライスまたはランダム アクセスのためのインデックスを使用しています。

経験則: インデックス + 値の enumerate に到達します。インデックス自体が主に必要な場合は、range(len()) を使用してください。 インデックスの計算のみが必要な場合は、Python 範囲の例 をさらに詳しく説明します。

パフォーマンスに関する考慮事項

enumerate は O(n) で遅延しているため、list() でラップしない限り、追加のペアのリストは割り当てられません。実際には、ループ内で list.index() を呼び出すよりも高速かつ明確です (ループが O(n^2) になる可能性があります)。行にラベルを付けるだけの場合、enumerate はメモリをフラットに保ちながら行番号を提供します。

列挙のその他の使用例

ログのスキャン中にエラー行にフラグを立てます。

lines = [
    "INFO connected",
    "ERROR timeout",
    "INFO retry",
]

for line_no, line in enumerate(lines, start=1):
    if "ERROR" in line:
        print(f"Line {line_no}: {line}")

これにより、各エラーに付けられた正確な行番号が保持され、デバッグとインシデントのレビューが高速化されます。 enumerate は任意の反復可能オブジェクトを受け入れるため、ファイルに対しても同様に機能します。

インデックスを使用してリストを正規化します。

names = ["  ada", "grace ", "  linus"]
for i, name in enumerate(names):
    # Update by index when you need to mutate the list in place.
    names[i] = name.strip().title()

print(names)

これにより、データを同じリスト内に保持しながら、割り当てる必要があるインデックスが得られます。 手動カウンターを管理するよりも明確で、ループを読みやすく保ちます。