「見つかったら止める」ができないと、無駄に回数を重ねます。初心者向けに、実際に回る回数を数える例で、どれくらい違いが出るかを体感できるように説明します。
早期終了のねらい
- 目的: 条件が満たされた瞬間に処理を打ち切って、残りの探索・計算を行わない。
- 効果: ループの「平均的な回転数」を減らす。特に「見つかる確率が高い」「前半で見つかりやすい」タスクで効く。
- 直観: 探しているものが先頭近くにあるとき、最後まで回すのは無駄。
例題1:リストから最初のゼロを探す(回数の違いを可視化)
break あり(最初に見つかったら止める)
numbers = [0] + list(range(1, 100000)) # 先頭にゼロ
checks = 0
for n in numbers:
checks += 1
if n == 0:
break
print("チェック回数:", checks) # 1
Pythonbreak なし(最後まで回す)
numbers = [0] + list(range(1, 100000))
checks = 0
for n in numbers:
checks += 1
if n == 0:
# 見つけても止めない(わざと非効率)
pass
print("チェック回数:", checks) # 100000
Python- 違い: 先頭で見つかるのに、break がないと全件走査してしまい、回数が 1 → 100000 に激増。
- 平均的なケース: ゼロが最初の1万件のどこかにあるなら、break ありは平均約5000回、なしは常に100000回。
例題2:ネストしたループの早期終了(差が一気に膨らむ)
break あり(内側ループだけ止まる)
grid = [[0] + list(range(1, 1000)) for _ in range(1000)] # 各行の先頭が0
checks = 0
for row in grid:
for x in row:
checks += 1
if x == 0:
break # 1行目の0で内側を止める(各行につき1回で終わる)
print("チェック回数:", checks) # 約 1000
Pythonbreak なし(毎行で全列を走査)
grid = [[0] + list(range(1, 1000)) for _ in range(1000)]
checks = 0
for row in grid:
for x in row:
checks += 1
if x == 0:
pass # 止めない
print("チェック回数:", checks) # 約 1,000,000
Python- 違い: 行×列の全探索か、各行1回で止めるかで、約1000倍の差。
- ポイント: ネストが深いほど「早期終了の恩恵」は指数的に効く。
例題3:見つからないケースでも差が出る設計
- 見つかる前提: break は平均回数を減らす(ベストケースが劇的に短い)。
- 見つからない前提: 最悪ケースはどちらも全件。ただし「途中で条件を狭める」「早めに不成立を判定する」設計で、不要な内側処理を減らせる。
# 不成立を早めに返せる return の設計例(関数化)
def has_even_then_multiple_of_three(nums):
# 偶数が1件もなければ、後続の「3の倍数判定」をしないで終了
if all(n % 2 == 1 for n in nums): # ここで早期不成立
return False
# 条件を満たす組合せを探す(実際はもっと複雑なロジックでも同じ考え方)
for n in nums:
if n % 2 == 0 and n % 3 == 0:
return True
return False
Python- 設計のコツ: 高コストなチェックの前に、安い否定条件でふるい落とす。
実務で効く早期終了パターン
- 検索タスク:
- 例: ログから最初のエラーレコードを見つける → 見つかったら読み込みや解析を止める。
- バリデーション:
- 例: 最初の不正入力を見つけたら残りの項目チェックを中断し、メッセージを返す。
- 最適化・探索:
- 例: 目的のスコアに到達したら、それ以上の候補生成を打ち切る(枝刈り)。
- ストリーム処理:
- 例: 一致が出たらネットワーク/ファイル読み込みを閉じる。
使い分けの指針と代替案
- 指針:
- 並びをなぞるなら for に break: シンプルで読みやすく、平均コストを下げられる。
- 処理全体を止めたいなら関数で return: 見つかった瞬間に関数ごと終了。外側の処理も不要化。
- 代替案(break を避けたい場合):
- フラグ+while 条件: ループ条件に「見つかったら回さない」を組み込む。
- next+ジェネレータ: 最初の一致だけ取り出して終わる。
# ジェネレータ+next(最初の一致だけ)
items = [0] + list(range(1, 100000))
first_zero = next((x for x in items if x == 0), None)
print(first_zero) # 0
Python- 注意: 「読みやすさ」と「意図の明確さ」を損なわない範囲で早期終了を入れるのがコツ。
効率は「計算量の最悪値」より「平均的な実行パターン」で差が出ます。あなたのデータで「どこで見つかることが多いか」を意識し、止められるところで止める設計にすると、体感速度が大きく変わります。

