Pythonの if 文において else が「条件に合致しなかった場合」を意味することは広く知られています。しかし、Pythonでは for 文や while 文といったループ構文に対しても else を記述できることは、意外と知られていません。
ループにおける else ブロックは、**「ループが break 文で中断されることなく、最後まで正常に完了した場合」**にのみ実行されるという、非常にユニークで便利な特性を持っています。
この記事では、この for-else 構文の仕組みと、フラグ変数を使わずに探索処理を記述する方法について解説します。
for-else 文の基本動作
通常、ループ処理で特定のデータを探す場合、「見つかったら break でループを抜ける」という実装をよく行います。この時、「最後まで見つからなかった場合」の処理をどう書くかが課題になります。
for-else 文を使うと、これを直感的に記述できます。
構文:
for 変数 in イテラブル:
if 条件:
# 条件を満たしたらループを中断
break
else:
# break されずにループが終了した場合に実行される
具体的な使用例:接続可能なサーバーの探索
例として、複数のサーバーリストに対して順に接続を試み、どれか1つでも接続できれば成功、すべてのサーバーで接続に失敗した場合はエラーを表示するプログラムを作成します。
import random
def try_connect(server_name):
"""
サーバーへの接続をシミュレートする関数
(ランダムにTrue/Falseを返す)
"""
# 実際の実装ではネットワーク接続処理などを行う
is_success = random.choice([True, False])
print(f"[{server_name}] 接続試行中... 結果: {'成功' if is_success else '失敗'}")
return is_success
# 接続先サーバーのリスト
backup_servers = ["server-alpha", "server-beta", "server-gamma"]
print("--- 接続処理開始 ---")
for server in backup_servers:
# 接続に成功した場合
if try_connect(server):
print(f"接続を確立しました: {server}")
# 目的を達成したのでループを抜ける
break
else:
# ループが一度も break されなかった場合 (全サーバー失敗) に実行
print("エラー: すべてのサーバーへの接続に失敗しました。")
print("--- 処理終了 ---")
実行結果パターンA(成功時):
--- 接続処理開始 ---
[server-alpha] 接続試行中... 結果: 失敗
[server-beta] 接続試行中... 結果: 成功
接続を確立しました: server-beta
--- 処理終了 ---
server-beta で break が実行されたため、else ブロック(エラー表示)はスキップされています。
実行結果パターンB(全失敗時):
--- 接続処理開始 ---
[server-alpha] 接続試行中... 結果: 失敗
[server-beta] 接続試行中... 結果: 失敗
[server-gamma] 接続試行中... 結果: 失敗
エラー: すべてのサーバーへの接続に失敗しました。
--- 処理終了 ---
最後まで break が実行されなかったため、else ブロックが実行されました。
フラグ変数を使った場合との比較
もし for-else を使わずに同じロジックを実装する場合、以下のように状態を管理する変数(フラグ)が必要になります。
# 従来の書き方 (フラグ変数を使用)
is_connected = False # フラグ変数
for server in backup_servers:
if try_connect(server):
print(f"接続を確立しました: {server}")
is_connected = True # フラグを更新
break
# ループ後にフラグを確認
if not is_connected:
print("エラー: すべてのサーバーへの接続に失敗しました。")
for-else 構文を使用することで、この is_connected のような一時的な変数が不要になり、コードがよりシンプルになります。
まとめ
- Pythonのループ (
for,while) にはelseブロックを追加できます。 - この
elseブロックは、ループがbreakされずに最後まで回りきった場合 にのみ実行されます。 - 「探索して見つからなかった場合」の処理を記述する際に、フラグ変数を排除できるため非常に有用です。
if文のelseとは意味合いが異なるため、直感的に理解できるようコメントを添えると親切です。
