圧力測定値を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
処理の流れは次のようになります。
- リストから
7.0を取り出す pressure_mpaへ代入して、インデントされた処理を実行する- 次の
14.0を取り出して同じ処理を実行する - 要素がなくなるまで繰り返す
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
処理の順番は次のとおりです。
retry_count < max_retriesを評価するTrueならインデント内を実行する- 再び条件を評価する
- 条件が
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文へ戻した方が安全です。
実務例:複数の工学データを安全に処理する
複数のシリンダについて、圧力と受圧面積から理論推力を計算します。
ここでは次の単位を使います。
- :圧力 MPa
- :受圧面積 mm²
- :推力 N
入力データには、欠損値と許容範囲外の値も含めます。
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で実行確認済みです。
安全に複数データを処理するため、次の順番で確認しています。
- 欠損していないか
NaNや無限大ではないか- 圧力が許容範囲内か
- 面積が正数か
- 検証を通過したデータだけ計算する
- 処理件数を最後に表示する
不正な行を黙って捨てるのではなく、行番号、対象名、除外理由を表示している点も重要です。
なお、この計算結果は摩擦、背圧、圧力損失、安全率を含まない理論値です。コードが正常に繰り返されたことと、実機へ適用できる計算条件がそろっていることは別に確認します。
反復中に元のリストを変更しない
処理中のリストから要素を削除すると、まだ確認していない要素を飛ばす可能性があります。
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には状態更新と終了条件が必要- リスト内包表記は単純な変換や抽出に限定すると読みやすい
- 複数データの処理では、欠損、有限性、範囲、単位を検証する
- 成功件数だけでなく、除外したデータと理由も確認する
繰り返し処理はコードを短くするためだけの仕組みではありません。すべての入力へ同じ検証規則を適用し、結果を再現可能にするための基盤です。

