Pythonの繰り返し処理を理解する|for・while・range・enumerate・zipの基本

「Pythonの繰り返し処理を理解する|for・while・range・enumerate・zipの基本」の内容を表す技術イラスト

圧力測定値を10件確認する、部品表の各行を変換する、複数の設計条件から計算結果を作る。このように、同じ種類の処理を複数のデータへ適用するときに使うのが繰り返し処理です。

Pythonには、主に2種類の繰り返しがあります。

  • for:コレクションなどから要素を順番に取り出す
  • while:条件が成立している間、処理を繰り返す

この記事では、range()、enumerate()、zip()も組み合わせ、欠損値や異常値を含むデータを安全に処理する方法まで確認します。

目次

今日の到達点

この記事を読み終えると、次のことができるようになります。

  • forで複数の要素を順番に処理できる
  • range()で回数や整数の範囲を指定できる
  • enumerate()で行番号と要素を同時に取得できる
  • zip()で対応する複数のデータを組み合わせられる
  • whileの継続条件を設計できる
  • breakとcontinueを使い分けられる
  • 無限ループが発生する原因を説明できる
  • 読みやすい範囲でリスト内包表記を使用できる
  • 欠損値や範囲外の値を除外しながら複数データを処理できる

for文で要素を順番に処理する

for文は、リストなどから要素を1個ずつ取り出して処理します。

pressures_mpa = [7.0, 14.0, 21.0]

for pressure_mpa in pressures_mpa:
    print(f"{pressure_mpa:.1f} MPa")

実行結果です。

7.0 MPa
14.0 MPa
21.0 MPa

処理の流れは次のようになります。

  1. リストから7.0を取り出す
  2. pressure_mpaへ代入して、インデントされた処理を実行する
  3. 次の14.0を取り出して同じ処理を実行する
  4. 要素がなくなるまで繰り返す

Pythonのfor文は、他言語で見られるカウンタ変数中心の構文とは異なり、反復可能なオブジェクトから要素を順番に取得します。Python公式チュートリアルでも、シーケンスの要素を出現順に反復すると説明されています。

変数名はxのような抽象名ではなく、値の意味と単位が分かる名前にすると安全です。

for pressure_mpa in pressures_mpa:
    ...

rangeで整数の範囲を作る

処理を決まった回数だけ繰り返したい場合は、range()を使用できます。

for test_no in range(1, 4):
    print(f"Test {test_no}")

実行結果です。

Test 1
Test 2
Test 3

range(1, 4)では、開始値の1を含み、終了値の4を含みません。

1, 2, 3

主な書き方は次の3つです。

書き方生成する整数
range(4)0、1、2、3
range(1, 4)1、2、3
range(0, 10, 2)0、2、4、6、8

3番目の引数は増分です。

for position_mm in range(0, 501, 100):
    print(f"{position_mm} mm")

実行結果です。

0 mm
100 mm
200 mm
300 mm
400 mm
500 mm

range()が返すのはリストではなく、必要な整数を順番に生成できるrangeオブジェクトです。大きな範囲を指定しても、すべての整数をリストとして先に作るわけではありません。Python公式チュートリアルで詳細を確認できます。

データ自体を処理したい場合は、インデックスだけを生成するより、要素へ直接forを適用する方が読みやすくなります。

# 要素へ直接アクセスできる
for pressure_mpa in pressures_mpa:
    print(pressure_mpa)

enumerateで番号と要素を取得する

CSVの行番号や検査項目番号も必要な場合は、enumerate()を使用します。

components = ["Pump", "Valve", "Cylinder"]

for row_no, component_name in enumerate(components, start=1):
    print(f"{row_no}: {component_name}")

実行結果です。

1: Pump
2: Valve
3: Cylinder

start=1を指定すると、番号が1から始まります。省略した場合は0から始まります。

次のように、range(len(...))でインデックスを作ることもできます。

for index in range(len(components)):
    print(index, components[index])

しかし、番号と要素の両方が必要なら、enumerate()の方が目的を直接表現できます。

for index, component_name in enumerate(components):
    print(index, component_name)

Python公式ドキュメントのループ方法でも、位置と値を同時に取得する方法としてenumerate()が紹介されています。

zipで対応するデータを組み合わせる

部品名と圧力値など、位置が対応している複数のデータを同時に処理するにはzip()を使えます。

component_names = ["Cylinder A", "Cylinder B"]
pressures_mpa = [14.0, 7.0]

for component_name, pressure_mpa in zip(
    component_names,
    pressures_mpa,
    strict=True,
):
    print(f"{component_name}: {pressure_mpa:.1f} MPa")

実行結果です。

Cylinder A: 14.0 MPa
Cylinder B: 7.0 MPa

zip()は、各データの同じ位置にある要素をタプルとして組み合わせます。

注意したいのは、通常のzip()は長さが異なる場合、最も短いデータに合わせて終了することです。

names = ["A", "B", "C"]
values = [10, 20]

print(list(zip(names, values)))

実行結果です。

[('A', 10), ('B', 20)]

"C"は処理されません。エラーも自動では発生しないため、データの欠落を見逃す可能性があります。

要素数が一致することを前提とする処理では、strict=Trueを指定できます。

for name, value in zip(names, values, strict=True):
    print(name, value)

この例では長さが異なるため、ValueErrorが発生します。

Python公式のzip()ドキュメントでも、入力データの長さが等しいと想定する場合はstrict=Trueにより不整合を検出できると説明されています。部品番号と測定値など、対応関係が重要なデータでは有効です。

while文で条件が成立する間繰り返す

while文は、条件がTrueである間、処理を繰り返します。

retry_count = 0
max_retries = 3

while retry_count < max_retries:
    retry_count += 1
    print(f"Attempt {retry_count}")

実行結果です。

Attempt 1
Attempt 2
Attempt 3

処理の順番は次のとおりです。

  1. retry_count < max_retriesを評価する
  2. Trueならインデント内を実行する
  3. 再び条件を評価する
  4. 条件がFalseになると終了する

while文の仕様はPython言語リファレンスで確認できます。

回数が最初から決まっている処理なら、一般にforとrange()の方が終了条件を読み取りやすくなります。

for attempt_no in range(1, 4):
    print(f"Attempt {attempt_no}")

一方、次のような処理はwhileに向いています。

  • 正常な入力を受け取るまで繰り返す
  • 最大試行回数まで再試行する
  • センサー値が目標範囲へ入るまで監視する
  • キューに処理対象が残っている間だけ続ける

実際の装置制御では、ループ条件だけに頼らず、タイムアウト、非常停止、通信異常などの終了条件も設計する必要があります。

無限ループに注意する

whileの条件が永遠にTrueのままだと、処理は終了しません。

retry_count = 0

while retry_count < 3:
    print("Retrying...")

このコードではretry_countが更新されないため、無限ループになります。

修正例です。

retry_count = 0

while retry_count < 3:
    print("Retrying...")
    retry_count += 1

意図的にwhile Trueを使うこともできますが、必ず終了経路を確認します。

while True:
    command = input("Command [start/quit]: ").strip().lower()

    if command == "quit":
        break

    if command == "start":
        print("Started")

外部入力や通信を待つループでは、入力が永久に来ない可能性もあります。実務では最大回数や経過時間による制限を設けることが重要です。

breakとcontinueの違い

breakはループ全体を終了します。continueは現在の回だけ残りの処理を飛ばし、次の要素へ進みます。

readings_mpa = [14.0, None, -1.0, 16.5, 12.0]
valid_readings_mpa = []

for pressure_mpa in readings_mpa:
    if pressure_mpa is None or pressure_mpa < 0:
        continue

    if pressure_mpa > 16.0:
        print(f"Limit exceeded: {pressure_mpa:.1f} MPa")
        break

    valid_readings_mpa.append(pressure_mpa)

print(valid_readings_mpa)

実行結果です。

Limit exceeded: 16.5 MPa
[14.0]

この処理では次の判断をしています。

  • None:欠損値なのでcontinue
  • 負の圧力:異常値なのでcontinue
  • 16 MPa超過:処理を続けるべきでないためbreak
  • その他:有効値として保存

breakが実行された後にある12.0は処理されません。

異常値を記録して残りも処理したい場合は、breakではなくcontinueを使用します。どちらを選ぶかは、異常発生後も処理を継続してよいかという業務ルールで決まります。

リスト内包表記は単純な変換に使う

リスト内包表記を使うと、各要素を変換した新しいリストを簡潔に作れます。

pressures_mpa = [7.0, 14.0, 21.0]

pressures_pa = [
    pressure_mpa * 1_000_000
    for pressure_mpa in pressures_mpa
]

print(pressures_pa)

実行結果です。

[7000000.0, 14000000.0, 21000000.0]

通常のfor文で書くと次のようになります。

pressures_pa = []

for pressure_mpa in pressures_mpa:
    pressures_pa.append(pressure_mpa * 1_000_000)

単純な変換や短い条件なら、リスト内包表記は読みやすくなります。

一方、次の処理を詰め込みすぎると理解しにくくなります。

  • 複数段階の条件判定
  • 例外処理
  • ログ出力
  • 単位や範囲の検証
  • 複雑な計算式

処理内容を一読して説明できない場合は、通常のfor文へ戻した方が安全です。

実務例:複数の工学データを安全に処理する

複数のシリンダについて、圧力と受圧面積から理論推力を計算します。F=pAF=pA

ここでは次の単位を使います。

  • pp:圧力 MPa
  • AA:受圧面積 mm²
  • FF:推力 N
  • 1 MPa=1 N/mm21\ \mathrm{MPa}=1\ \mathrm{N/mm^2}

入力データには、欠損値と許容範囲外の値も含めます。

import math

components = [
    {
        "name": "Cylinder A",
        "pressure_mpa": 14.0,
        "area_mm2": 5026.548,
    },
    {
        "name": "Cylinder B",
        "pressure_mpa": None,
        "area_mm2": 1963.495,
    },
    {
        "name": "Cylinder C",
        "pressure_mpa": 18.0,
        "area_mm2": 3141.593,
    },
    {
        "name": "Cylinder D",
        "pressure_mpa": 10.0,
        "area_mm2": 1256.637,
    },
]

results = []

for row_no, component in enumerate(components, start=1):
    name = component["name"]
    pressure_mpa = component["pressure_mpa"]
    area_mm2 = component["area_mm2"]

    if pressure_mpa is None:
        print(
            f"Row {row_no}: {name} - "
            "skipped (pressure is missing)"
        )
        continue

    if not math.isfinite(pressure_mpa) or not math.isfinite(area_mm2):
        print(
            f"Row {row_no}: {name} - "
            "skipped (non-finite value)"
        )
        continue

    if not (0 < pressure_mpa <= 16.0):
        print(
            f"Row {row_no}: {name} - "
            "skipped (pressure out of range)"
        )
        continue

    if area_mm2 <= 0:
        print(
            f"Row {row_no}: {name} - "
            "skipped (area must be positive)"
        )
        continue

    force_kn = pressure_mpa * area_mm2 / 1000

    results.append({
        "name": name,
        "force_kn": force_kn,
    })

    print(f"Row {row_no}: {name} - {force_kn:.2f} kN")

print(f"Processed: {len(results)}/{len(components)}")

実行結果です。

Row 1: Cylinder A - 70.37 kN
Row 2: Cylinder B - skipped (pressure is missing)
Row 3: Cylinder C - skipped (pressure out of range)
Row 4: Cylinder D - 12.57 kN
Processed: 2/4

このコードはPython 3.12.14で実行確認済みです。

安全に複数データを処理するため、次の順番で確認しています。

  1. 欠損していないか
  2. NaNや無限大ではないか
  3. 圧力が許容範囲内か
  4. 面積が正数か
  5. 検証を通過したデータだけ計算する
  6. 処理件数を最後に表示する

不正な行を黙って捨てるのではなく、行番号、対象名、除外理由を表示している点も重要です。

なお、この計算結果は摩擦、背圧、圧力損失、安全率を含まない理論値です。コードが正常に繰り返されたことと、実機へ適用できる計算条件がそろっていることは別に確認します。

反復中に元のリストを変更しない

処理中のリストから要素を削除すると、まだ確認していない要素を飛ばす可能性があります。

values = [5, -1, -2, 8]

for value in values:
    if value < 0:
        values.remove(value)

負の値を除外したい場合は、新しいリストを作る方が明確です。

values = [5, -1, -2, 8]
valid_values = []

for value in values:
    if value >= 0:
        valid_values.append(value)

print(valid_values)

実行結果です。

[5, 8]

単純な条件なら、リスト内包表記でも記述できます。

valid_values = [value for value in values if value >= 0]

Python公式チュートリアルでも、反復中のコレクション変更は扱いに注意し、コピーを反復するか新しいコレクションを作る方法が示されています。for文の公式解説を参照してください。

よくある失敗

rangeの終了値を含むと思う

for number in range(1, 5):
    print(number)

出力されるのは1から4です。5は含まれません。

whileの状態を更新していない

count = 0

while count < 5:
    print(count)

countが変化しないため終了しません。ループ内で終了条件へ近づく更新が必要です。

continueより後ろでカウンタを更新する

count = 0

while count < 5:
    if count == 2:
        continue

    count += 1

countが2になると更新処理へ到達できず、無限ループになります。whileとcontinueを組み合わせる場合は、状態更新の位置を確認してください。

zipが余った値を検出すると思う

通常のzip()は、短い方へ合わせて終了します。長さの一致が必須ならstrict=Trueを指定します。

エラーがない行だけ確認する

大量データの処理では、成功結果だけでなく次も残します。

  • 入力件数
  • 成功件数
  • 除外件数
  • 除外理由
  • 処理を中断した条件

「最後まで動いた」だけでは、すべてのデータが正しく処理されたとは判断できません。

練習問題

5回の検査番号を表示する

range()を使い、Inspection 1からInspection 5まで表示してください。

解答例です。

for inspection_no in range(1, 6):
    print(f"Inspection {inspection_no}")

実行結果です。

Inspection 1
Inspection 2
Inspection 3
Inspection 4
Inspection 5

終了値を含まないため、range(1, 6)とする点が確認項目です。

部品名へ通し番号を付ける

次の部品名へ、1から始まる番号を付けてください。

part_names = ["Pump", "Valve", "Cylinder"]

解答例です。

for row_no, part_name in enumerate(part_names, start=1):
    print(f"{row_no}: {part_name}")

実行結果です。

1: Pump
2: Valve
3: Cylinder

対応する流量を単位変換する

ライン名と流量をzip()で組み合わせ、L/minからL/sへ変換してください。

flow_names = ["Line A", "Line B", "Line C"]
flows_l_min = [30.0, 60.0, 90.0]

解答例です。

for flow_name, flow_l_min in zip(
    flow_names,
    flows_l_min,
    strict=True,
):
    flow_l_s = flow_l_min / 60
    print(f"{flow_name}: {flow_l_s:.2f} L/s")

実行結果です。

Line A: 0.50 L/s
Line B: 1.00 L/s
Line C: 1.50 L/s

確認する観点は、対応関係、データ数の一致、単位換算です。

まとめ

Pythonの繰り返し処理は、複数のデータへ同じ処理を適用するための基本機能です。

  • forは要素を順番に処理する
  • range()は整数の範囲を表し、終了値を含まない
  • enumerate()は番号と要素を同時に取得する
  • zip()は対応する複数データをまとめる
  • 長さの一致が必要なzip()ではstrict=Trueを検討する
  • whileは条件が成立している間、処理を繰り返す
  • breakはループを終了し、continueは次の反復へ進む
  • whileには状態更新と終了条件が必要
  • リスト内包表記は単純な変換や抽出に限定すると読みやすい
  • 複数データの処理では、欠損、有限性、範囲、単位を検証する
  • 成功件数だけでなく、除外したデータと理由も確認する

繰り返し処理はコードを短くするためだけの仕組みではありません。すべての入力へ同じ検証規則を適用し、結果を再現可能にするための基盤です。

参考情報

参考になったらシェアしてください
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

機械設計・油圧・CAD・Python・AIなど、ものづくりに関わる技術を扱っています。工学知識を整理・構造化し、設計や自動化に再利用できる形へ変えていくことを目指しています。

目次