条件を満たす間だけ処理を繰り返すのがPythonのwhile
文です。
固定回数の反復(for
やrange()
)では扱いにくい、ユーザー入力や外部状態に応じた反復に向いています。
本記事では基本構文から条件式の書き方、そして無限ループを避ける安全な設計まで、初心者向けに丁寧に解説します。
Pythonのwhile文の基本
基本構文と動き
while文は「条件式がTrue
の間、ブロックを繰り返す」構文です。
条件は各反復の先頭で再評価され、False
になるとループが終了します。
基本形は次のとおりです。
# 1から3まで数える基本例
count = 1 # ループ変数(状態)
while count <= 3: # 条件式がTrueの間、繰り返す
print(f"count={count}")
count += 1 # ループ変数を更新(これを忘れると無限ループ)
print("done")
count=1
count=2
count=3
done
ポイントとして、初回から条件がFalse
なら本体は1回も実行されません。
また、ループ内部でcount += 1
のように状態を更新しないと、条件が変わらず無限ループになります。
使える場面のイメージ
「いつ終わるかが実行中に決まる」処理に向いています。
例えば以下のような場面です。
- ユーザーが「q」を入力するまで繰り返す
- ファイルやキューからの読み取りを、データがある間だけ続ける
- センサー値がしきい値に達するまで待機する
以下に、while文が活きる具体例をまとめます。
場面 | 終了条件の例 | whileでの書き方のヒント |
---|---|---|
入力を受け付けるフォーム | 入力が”q”なら終了 | while True + break で番兵値を使う |
キュー処理 | キューが空になったら終了 | while queue の真偽値で判定 |
リトライ | 成功するか上限回数到達 | 条件をand で合成しガードを付ける |
固定回数が決まっている反復はfor
が向いていますが、終了条件が動的に決まるならwhile
が適しています。
while文の条件式の書き方
数値の比較と真偽値
最も基本的なのは、数値の比較を用いた終了条件です。
「0になったら終わる」「n以下の間は続ける」といった書き方が読みやすく安全です。
# カウントダウン(明示的な比較が読みやすい)
n = 5
while n > 0: # nが0より大きい間は続く
print(f"n={n}")
n -= 1 # 状態の更新
print("finish")
n=5
n=4
n=3
n=2
n=1
finish
Pythonでは数値やコレクションには真偽値の概念(真理値評価)があり、0
や空列はFalse
、それ以外はTrue
として扱われます。
そのため次のようにも書けます。
# 真理値評価を使った短い書き方(やや上級者向け)
n = 3
while n: # nが0でない間はTrue
print(f"n={n}")
n -= 1
print("done")
n=3
n=2
n=1
done
ただし、初心者のうちは明示的な比較(n > 0
など)の方が意図が伝わりやすいので推奨です。
複合条件はand
、or
、not
で合成できます。
# 複合条件の例: 5以下の間に限り、停止フラグが立っていなければ進める
n = 1
limit = 5
paused = False
while n <= limit and not paused:
print(f"n={n}")
if n == 3:
paused = True # 途中で停止条件が満たされたら以後は回らない
n += 1
print("loop end")
n=1
n=2
n=3
loop end
フラグ変数(bool)で制御
フラグ変数(例: running
)は、ループ継続可否を明示する分かりやすい方法です。
外部からの停止指示や例外条件にも対応しやすくなります。
# フラグ変数でループのON/OFFを管理する
running = True
step = 0
while running:
print(f"step={step}")
step += 1
if step >= 3:
running = False # 終了フラグを立てて抜ける(次の判定でFalse)
print("stopped")
step=0
step=1
step=2
stopped
「何が起きたら止まるのか」をフラグ名に込めると、後から読んだときに意図が伝わりやすいです。
入力で終了条件を作る
ユーザーの入力で終わるループはwhile True
とbreak
を組み合わせると書きやすいです。
いわゆる番兵値(例: “q”)で終了します。
# 入力された数字を合計し、"q"で終了する
total = 0
while True:
s = input("数字を入力(終わりはq): ")
if s == "q":
break # ループを抜ける
# 数値チェック(負号付き整数にも簡易対応)
txt = s.strip()
if not (txt.lstrip("-").isdigit()):
print("数字を入力してください")
continue # 今回分はスキップ
total += int(txt)
print(f"合計: {total}")
数字を入力(終わりはq): 10
数字を入力(終わりはq): 5
数字を入力(終わりはq): x
数字を入力してください
数字を入力(終わりはq): q
合計: 15
Python 3.8以降では代入式演算子(通称ウォルラス演算子)で、入力と判定を1行にまとめることもできます。
# ウォルラス演算子(:=)で簡潔に書く(Python 3.8+)
while (s := input("> ")) != "q":
print(f"あなたが入力: {s}")
print("bye")
> hello
あなたが入力: hello
> world
あなたが入力: world
> q
bye
無限ループの回避術
ループ変数を必ず更新する
状態更新の抜け漏れは無限ループの最頻出原因です。
次の「悪い例」は条件が変化しません。
# 悪い例: iが更新されず永遠にi < 3がTrue
i = 0
while i < 3:
print(f"i={i}")
# i += 1 を忘れたため無限ループ
# 無限ループになるので実行しないこと
更新を忘れない場所(普通はループ末尾)で確実に行いましょう。
# 良い例: ループ末尾で一度だけ更新する
i = 0
while i < 3:
print(f"i={i}")
i += 1 # ここで必ず更新
print("ok")
i=0
i=1
i=2
ok
複数箇所で更新すると条件を読み間違えやすくなります。
できるだけ更新箇所は1つに絞るのが安全です。
終了条件を先に決める
コードを書く前に「正常終了」になる条件を文章で先に決めると、無限ループを避けやすくなります。
例えば「タスクがなくなる」または「キャンセル指示が来たら終了」と決めると次のように実装できます。
# タスク処理: タスクが空になる or キャンセル指示で終了する
tasks = ["A", "B", "C"]
aborted = False
while tasks and not aborted: # 正常終了の条件を先に作る
task = tasks.pop(0)
print(f"do {task}")
if task == "B":
aborted = True # 途中キャンセルの例
if aborted:
print("中断されました")
else:
print("すべてのタスクを処理しました")
do A
do B
中断されました
終了条件を先に日本語で書き出し、それをそのまま論理式にするのがコツです。
複雑なら小さな関数に分けてwhile should_continue(...)
のように名付けると読みやすくなります。
ガード(上限回数)を付ける
外部要因でいつまでも終わらない可能性がある場合、安全装置として上限回数(ガード)を付けるのが実務では定石です。
# 成功するか、上限回数に達したら諦めるリトライ
max_tries = 5
tries = 0
success = False
def operation_will_succeed_on_third_try(current_try: int) -> bool:
# デモ用: 3回目で成功することにする
return current_try == 3
while tries < max_tries and not success:
tries += 1
print(f"{tries}回目の試行...")
success = operation_will_succeed_on_third_try(tries)
if success:
print(f"{tries}回目で成功しました")
else:
print("上限回数に達したため中止しました")
1回目の試行...
2回目の試行...
3回目の試行...
3回目で成功しました
ガードは最後の盾です。
根本原因を直すことに加えて、障害時にシステムが固まらないように備えておきましょう。
Python初心者がつまずくポイント
条件がずっとTrueになる
実装の意図に反して終了条件に到達しないと、結果的に永遠にTrueになります。
典型例が浮動小数の比較です。
# 悪い例: 浮動小数の誤差でxがちょうど1.0にならず終わらない可能性
x = 0.0
while x != 1.0:
x += 0.1 # 0.1は2進小数で正確に表せず、イコールにならない
print("終わり")
対策は整数カウンタで管理するか、誤差を許容する比較に切り替えることです。
# 整数カウンタで10回だけ0.1ずつ加算
x = 0.0
i = 0
while i < 10:
x += 0.1
i += 1
print(f"x={x} (10回で終了)")
x=0.9999999999999999 (10回で終了)
# iscloseで誤差を許容して終了させる方法
from math import isclose
x = 0.0
while not isclose(x, 1.0, rel_tol=1e-12, abs_tol=1e-12):
x += 0.1
if x > 2.0: # 予防のガード
print("想定外に到達しないため中止")
break
print(f"x={x}")
x=0.9999999999999999
更新忘れでループが止まらない
入力をループの外で1回だけ取得して、そのまま更新しないのもあるあるです。
# 悪い例: user_inputが更新されない
user_input = input("入力(qで終了): ")
while user_input != "q":
print("続行中...")
# user_input = input(...) を忘れたため、二度と変わらない
修正は、ループの中で毎回入力を更新するか、while True
とbreak
で番兵値を使うことです。
# 良い例: 毎回入力を取得し、番兵値でbreak
while True:
user_input = input("入力(qで終了): ")
if user_input == "q":
print("終了します")
break
print(f"受け取った値: {user_input}")
入力(qで終了): a
受け取った値: a
入力(qで終了): b
受け取った値: b
入力(qで終了): q
終了します
printデバッグで流れを確認する
挙動が分からないときは変数の値とループ回数をprintするのが手っ取り早いです。
f文字列でラベルを付け、開始時と更新後の両方を観察すると原因が見えます。
# ループの流れと変数の変化を見える化
i = 0
limit = 3
while i < limit:
print(f"[debug] start: i={i}, limit={limit}")
i += 1
print(f"[debug] end: i={i}")
print("完了")
[debug] start: i=0, limit=3
[debug] end: i=1
[debug] start: i=1, limit=3
[debug] end: i=2
[debug] start: i=2, limit=3
[debug] end: i=3
完了
printが多すぎて見づらい場合は、特定条件のときだけ出す、数回に1回だけ出すなどの工夫を加えましょう。
まとめ
本記事ではwhile
文の基本から、安全な条件式の書き方、無限ループ回避の設計までを解説しました。
「終了条件を先に決める」「状態は毎回更新する」「必要に応じてガードを付ける」という3点を押さえれば、初心者でも安心してwhile
を使いこなせます。
加えて、入力や外部状態による動的な反復にはwhile True
+ break
の番兵パターンが有効です。
最後に、不調時はprintデバッグで流れを見える化し、条件が本当にFalse
になるのか、更新が行われているのかを一つずつ確認しましょう。