他のプログラミング言語からPythonに移行してきた開発者が、まず戸惑うことの一つに「do-while文が存在しない」という点が挙げられます。
C言語やJava、JavaScriptなどでは当たり前のように使われている、「少なくとも一度は処理を実行してから条件判定を行う」というループ構造は、Pythonの言語仕様には直接含まれていません。
しかし、Pythonにおいてdo-while文のような挙動が必要になる場面は多々あります。
ユーザー入力を最低1回は求める場合や、初回の試行結果に基づいてループを継続するか判断するケースなどです。
Pythonでは、標準的なwhile文を工夫して使うことで、この仕組みをスマートに再現することができます。
本記事では、Pythonにおけるdo-while文の代用手法として、最も一般的で推奨される「while Trueとbreakを組み合わせた書き方」から、最新の代入演算子(セイウチ演算子)を活用した高度な記述までを詳しく紹介します。
Pythonにdo-while文が実装されていない理由
Pythonの開発チームは、言語をシンプルかつ読みやすく保つことを重視しています。
do-while文の導入については過去に何度も議論(PEP 315など)されてきましたが、最終的には「既存のwhile文とbreakの組み合わせで十分に対応可能である」という結論に至っています。
一般的なdo-while文は、ループの末尾で継続条件を確認する「後判定」という形式をとります。
これに対し、Pythonのwhile文はループの先頭で条件を確認する「前判定」です。
Pythonにおいて後判定を導入しようとすると、インデント構造が複雑になり、コードの可読性を損なう可能性があると考えられたため、明示的な構文としてのdo-whileは採用されませんでした。
そのため、Pythonエンジニアは特定のパターンを用いて同様のロジックを実現するのが一般的です。
基本の再現手法:while Trueとbreakの活用
Pythonでdo-while文の挙動を再現する最も標準的な方法は、while True:による無限ループを作成し、その内部の最後にif文とbreakを配置する方法です。
この書き方は「無限ループ」という言葉の響きほど危険ではなく、むしろフローが明確になるため、多くのライブラリやプロダクトコードで採用されています。
基本的な書き方の構成
この手法の最大の特徴は、ループの終了条件をループ内のどこにでも配置できるという柔軟性にあります。
do-while文を模倣する場合は、以下のコードブロックのように処理の最後に条件判定を記述します。
while True:
# 最初に実行したい処理をここに記述
print("この処理は必ず1回は実行されます")
# 終了条件を判定する
# 他の言語の do { ... } while (condition) の逆の条件(終了条件)を書く
is_running = False # 本来は動的なフラグや比較式
if not is_running:
break # 条件を満たした場合にループを抜ける
この処理は必ず1回は実行されます
この構成であれば、一度目の処理が確実に実行された後、if文によって継続か終了かが判断されます。
C言語などのdo-while(condition)では「継続条件」を書きますが、Pythonのbreakを用いる場合は「終了条件」を記述するという点に注意してください。
実用的な例:ユーザー入力のバリデーション
do-while文の代用が最も効果を発揮するのは、ユーザーからの入力を受け取り、それが妥当な値であるかどうかを判定するシーンです。
例えば、正の整数が入力されるまで繰り返し入力を求めるプログラムを考えてみましょう。
while True:
user_input = input("1以上の数値を入力してください: ")
# 入力値が数値であり、かつ1以上かどうかを確認
if user_input.isdigit() and int(user_input) >= 1:
print(f"入力された値: {user_input}")
break # 正しい入力が得られたのでループを終了
print("不正な入力です。もう一度入力してください。")
このコードでは、まずinput()関数が実行されます。
もし入力された値が条件を満たしていなければ、breakに到達せずにループの先頭に戻ります。
これにより、「最低1回は入力を促し、条件を満たすまで繰り返す」というdo-while文特有のロジックが完成します。
セイウチ演算子(:=)によるモダンなアプローチ
Python 3.8以降で導入された「代入演算子(:=)」、通称セイウチ演算子(Walrus Operator)を使用すると、さらにスマートにdo-while文に近い記述が可能です。
これは式の評価と変数への代入を同時に行うもので、コードをより簡潔に保つことができます。
セイウチ演算子を使ったサンプルコード
以下の例では、特定の文字列が入力されるまでループを継続する処理を記述しています。
# 'exit' と入力されるまでループを継続
while (user_msg := input("メッセージを入力(exitで終了): ")) != "exit":
print(f"送信されたメッセージ: {user_msg}")
厳密には、これは「前判定」のwhile文です。
しかし、条件式の中で代入と評価を同時に行っているため、他の言語におけるdo-while文に近い直感的な記述になっています。
ただし、この方法は「最初の1回を無条件で実行する」というよりは、「評価と入力を1行にまとめる」という側面に特化しています。
while文とdo-whileスタイル(擬似)の比較
Pythonにおける通常のwhile文と、while Trueを用いたdo-whileスタイルの違いを整理しましょう。
それぞれの特性を理解することで、状況に応じた最適な選択が可能になります。
| 特徴 | 通常のwhile文(前判定) | while True + break(後判定スタイル) |
|---|---|---|
| 最初の実行 | 条件がTrueの時のみ実行される | 必ず一度は実行される |
| 条件判定の場所 | ループの開始前 | ループ内の任意の位置(主に末尾) |
| 主な用途 | リストの処理や、最初から条件が決まっている場合 | ユーザー入力、リトライ処理、動的なフラグ判定 |
| コードの簡潔さ | 短い条件式なら非常にシンプル | 複雑な終了条件を柔軟に書ける |
このように、「まずやってみて、その結果次第で次を決める」というケースでは、後者のスタイルが圧倒的に書きやすく、読みやすくなります。
注意点:無限ループの防止と可読性
while Trueを使用する際に最も注意すべき点は、終了条件(break)の記述漏れです。
条件判定を誤ったり、特定の条件下でbreakに到達しなかったりすると、プログラムがフリーズしたりCPUリソースを過剰に消費したりする原因になります。
また、ループ内に複数のbreakやcontinueを散りばめると、処理の流れを追うのが難しくなります。
do-whileスタイルを維持するためには、できるだけループの末尾付近に一箇所だけ終了判定を置くというルールを自分の中で設けるのが、保守性の高いコードを書くためのコツです。
複雑なロジックを1つのループに詰め込みすぎていると感じた場合は、処理を関数として切り出し、その戻り値をループの判定条件に使用することを検討してください。
まとめ
Pythonには明示的なdo-while文は存在しませんが、while Trueとbreak、あるいは代入演算子(:=)を組み合わせることで、同等以上の柔軟なループ処理を実現できます。
特に「while True + break」のパターンは、Pythonにおける標準的な慣用句(イディオム)として定着しており、他のエンジニアが見ても意図が伝わりやすい書き方です。
「最初に一度だけ実行したいダミーの処理をwhile文の前に書く」といった冗長な回避策をとるのではなく、今回解説した正しい書き方を選択するようにしましょう。
Pythonの設計思想である「シンプルさ」を活かし、適切なループ構造を選ぶことで、バグの少ない、メンテナンス性に優れたプログラムを構築してください。
