# Pythonのループと条件分岐：for、while、range、enumerate、break、if/elif、match/case

URL: https://skillaria.top/ja/guides/python/cikly-python

Pythonのループは処理を繰り返す仕組みです。forはリストや範囲（range()）の要素を順に取り出し、whileは条件が成り立つ間繰り返します。breakでループを抜け、continueで今の回の残りを飛ばし、enumerate()で番号を付けられます。判断にはif/elif/elseを使い、データの形で分岐するならmatch/case（Python 3.10以降）を使います。

Pythonのループは、同じ処理を繰り返すために使います。買い物リストを1行ずつ処理する、ファイルの各行を読み込む、正しい数字が入力されるまで質問を続ける、といった場面です。Pythonのループには `for` と `while` の2種類があります。その中で判断するには `if/elif/else` の条件分岐や `match/case` を使います。ここでは、それぞれの道具を実際に使える例とともに見ていきます。

## 条件分岐：if、elif、else

if文は、条件式が真のときだけブロックを実行します。ブロックは4つのスペースのインデントで示します。Pythonには波かっこがないため、インデントが正しくないと、すぐに `IndentationError` が出ます。

```
spent = 4200
limit = 5000

if spent > limit:
    print("予算を超えました")
elif spent > limit * 0.8:
    print("予算の残りは20%未満です")
else:
    print("問題ありません")
```

`elif` の条件は上から順に調べられ、最初に当てはまったものだけが実行されます。そのため、厳しい条件は上に書きます。もし `spent > limit * 0.8` を先頭に置くと、予算超過のメッセージは決して表示されません。

### 何が「真」とみなされるか

条件に比較式を書く必要はありません。偽とみなされるのは `False`、`None`、ゼロ（`0`、`0.0`）、空のコレクション（`""`、`[]`、`{}`）です。それ以外はすべて真です。そのため「リストが空でないか」は短く書けます。

```
expenses = []
if not expenses:
    print("まだ支出はありません")
```

条件は `and`、`or`、`not` で組み合わせられます。範囲の判定は比較を連ねて書けます。例：`if 0 < amount <= 100_000:`。短い選択には三項演算子も使えます。例：`status = "多め" if spent > limit else "通常"`。

## Pythonのforループ：構文と例

Pythonの `for` は、Cのようなカウンタではなく、要素を1つずつ取り出す仕組みです。リスト、文字列、辞書、ファイル、範囲など、繰り返し可能なオブジェクトの要素を先頭から順に受け取ります。他の言語でいうforeachにあたるのが、Pythonの通常の `for` です。

```
expenses = [350, 1200, 89, 4500]
total = 0
for amount in expenses:
    total += amount
print(total)  # 6139
```

構文は `for 変数 in コレクション:` で、その後にインデントされたブロックが続きます。ループが終わった後も、変数には最後の値が残ります。これが役立つこともありますが、大きなプログラムで頼るのはおすすめしません。

### 文字列、リスト、辞書のループ

文字列は1文字ずつ、リストは要素ごとに処理されます。辞書をそのままループすると、キーが順に取り出されます。キーと値を同時に取り出すには `.items()` を使います。

```
by_category = {"食費": 3200, "交通費": 900, "映画": 600}

for category, amount in by_category.items():
    print(f"{category}: {amount}円")
```

値だけを取り出すには `.values()` を使います。ループの途中で辞書のサイズを変えるとエラーになります。`RuntimeError: dictionary changed size during iteration` が出ます。要素を削除したい場合は、コピーを回しましょう。例：`for key in list(d):`。

## range関数：数字で繰り返す

数字を順に回したいときは `range()` を使います。`range()` はメモリ上にリストを作らず、数字を1つずつ生成するので、`range(10**9)` でも一瞬で準備できます。

| 呼び出し | 生成される数字 |
| --- | --- |

| `range(5)` | 0, 1, 2, 3, 4 |

| `range(2, 6)` | 2, 3, 4, 5 |

| `range(0, 10, 3)` | 0, 3, 6, 9 |

| `range(5, 0, -1)` | 5, 4, 3, 2, 1 |

覚えておくべきルールは、終わりの値は範囲に含まれないことです。`range(1, 10)` は9で終わります。これは「1つずれる」エラーのよくある原因です。ステップは負にできますが、0にはできません。

```
for i in range(1, 4):
    print(f"{i}日目")
# 1日目
# 2日目
# 3日目
```

## enumerate：ループの中で番号を付ける

要素の番号が必要なとき、初心者は `for i in range(len(items))` と書きがちです。動きますが、読みにくくなります。`enumerate()` は「番号と要素」のペアを返します。`start` 引数で、数え始める番号を指定できます。

```
items = ["コーヒー", "タクシー", "昼食"]
for n, item in enumerate(items, start=1):
    print(n, item)
# 1 コーヒー
# 2 タクシー
# 3 昼食
```

2つのリストを並行して回すには `zip()` を使います。例：`for name, price in zip(names, prices):`。`zip()` は最も短いリストで止まります。Python 3.10以降では `strict=True` を渡すと、長さが違うときにエラーになります。

## Pythonのwhileループ

`while` は、条件が真の間ブロックを繰り返します。繰り返し回数が事前に分からないときに使います。正しい入力を待つ、データを最後まで読む、成功するまで問い合わせを繰り返す、といった場合です。

```
balance = 10_000
month = 0
while balance > 0:
    balance -= 2_700
    month += 1
print(f"お金は{month}か月分あります")  # 4
```

大きな落とし穴は、条件に使っている変数を変えるのを忘れることです。そうするとループが終わりません。プログラムが止まってしまったら、Ctrl+C を押してください。Pythonは `KeyboardInterrupt` で実行を中断します。

### 無限ループとdo while

無限ループは、わざと書くこともあります。`while True:` を書き、`break` で抜けるパターンです。Pythonには `do while` 構文がありません。代わりに、このパターンが後判定のループの役割を果たします。ブロックは必ず1回は実行され、判定はブロックの最後に来ます。

```
while True:
    raw = input("金額: ")
    if raw.isdigit():
        amount = int(raw)
        break
    print("整数を入力してください")
```

`for` で無限ループを作るのは珍しく、`itertools.count()` のような無限のイテレータを回すときだけです。

## breakとcontinue：ループを抜ける、回を飛ばす

`break` はループを直ちに終わらせ、ループの後のコードに進みます。`continue` は、今の回の残りを飛ばして次の回に進みます。

```
expenses = [350, -10, 1200, 0, 99_999, 89]

for amount in expenses:
    if amount  50_000:
        print("不審な金額のため停止します")
        break             # ループを抜ける
    print(amount)
```

表示されるのは 350 と 1200 で、その後に警告が出てループが終わります。89 には到達しません。どちらの文も、自分を含む一番内側のループに対してだけ働きます。

### ループのelse

`for` と `while` には、少し珍しい `else` 節もあります。ループが `break` なしで最後まで回ったときに実行されます。検索処理に便利です。

```
for amount in expenses:
    if amount > 50_000:
        print("大きな支出を見つけました")
        break
else:
    print("大きな支出はありません")
```

## 多重ループ（ネストしたループ）

ループの中にループを入れると、内側のループは外側の1回ごとに最後まで実行されます。表や行列を回ったり、組み合わせを作ったりするときに使います。

```
for row in range(1, 4):
    for col in range(1, 4):
        print(row * col, end="\t")
    print()
```

注意点が2つあります。1つ目は、計算量が急に増えることです。10,000個の要素を持つ2重ループは、1億回の処理になります。2つ目は、`break` が抜けられるのは内側のループだけという点です。両方を止めたいなら、ループを関数に入れて `return` で抜けるのが、フラグを使うより分かりやすい方法です。

## match/caseの使い方

Python 3.10以降では、`if cmd == ... elif ...` が長く続くときに `match` 文（PEP 634）が使えます。これは単なるswitchではありません。値を形のパターンと照合し、同時にその一部を変数に取り出せます。

```
def parse(text):
    match text.split():
        case ["add", item, amount]:
            return f"追加 {item}: {amount}"
        case ["list"] | ["ls"]:
            return "支出を表示"
        case ["quit"]:
            return "終了"
        case _:
            return "不明なコマンドです"

print(parse("add コーヒー 250"))  # 追加 コーヒー: 250
print(parse("add コーヒー"))      # 不明なコマンドです
```

パターン `["add", item, amount]` に一致するのは、要素がちょうど3つで、先頭が `"add"` のリストだけです。金額のないコマンドは、すべてを受け止める `_` の節に入ります。`|` は複数の候補をまとめます。

### 辞書のパターンとガード条件

辞書のパターンは、書いたキーだけを確認し、ほかのキーは無視します。`int(a)` は型を確認すると同時に値を取り出します。パターンの後に `if` を付けると、追加の条件（ガード）になります。

```
match event:
    case {"type": "expense", "amount": int(a)} if a > 10_000:
        print("大きな支出", a)
    case {"type": "expense", "amount": int(a)}:
        print("支出", a)
```

### matchの一番の落とし穴

`case` の後に裸の名前を書くと、それは比較ではなく取り込み（キャプチャ）になります。`case limit:` はどんな値にも一致し、その値を `limit` に入れてしまいます。定数と比べたいときは、`case Color.RED:` のようにドット付きの名前を使うか、リテラルを書きます。

Python 3.10以降でmatchの構文はほとんど変わっていません。Python 3.15では、小さな非対称性が解消されました。以前は、リテラルのパターンで数字の前にマイナス記号を付けた形しか使えませんでした。今は `case +1:` も書けます。古いバージョンでは、このコードは構文エラーになります。

## ループでよくあるミス

- **ループ中にリストを変更する。** `for` の中で要素を削除すると、隣の要素が飛ばされます。新しいリストを作るのが安全です。例：`clean = [x for x in items if x > 0]`。
- **rangeの終わり。** `range(1, n)` は `n` を含みません。
- **whileで条件の変数を変えない。** 無限ループになります。
- **ループの中で `+=` で文字列を連結する。** 量が多いと、`"".join(parts)` より遅くなります。
- **比較の代わりに代入する。** `if x = 5` は構文エラーです。比較には `==` を使います。

## ループの練習問題

1. 支出のリストから、負の値を除いて合計と平均を計算する。
2. 多重ループで、1〜9の九九の表を表示する。
3. ユーザーが空文字を入力するまで数字を尋ね、最後に最大値を表示する。
4. リストの中で最初に1000より大きい数字を探し、なければその旨を表示する（`for ... else` を使う）。
5. `match` で `add`、`del`、`list` のコマンドを解釈する。

## まとめ

Pythonのループは、基本的に2つの文です。`for` はコレクションや `range()` の要素を順に処理し、`while` は条件が真の間繰り返します。`break` と `continue` で流れを制御し、`enumerate()` と `zip()` は手作業のカウンタを不要にし、`if/elif/else` と `match/case` が判断を担当します。これらの道具はすべて、講座の家計簿ツールを題材にした講義で実際に使いながら解説しています。

## FAQ

**Pythonのforとwhileの違いは何ですか？**

forは用意された並びを順に処理し、いつ終わるかを自分で把握しています。whileは条件が真の間繰り返します。回数が決まっているか、コレクションを回すならfor、何かの出来事を待つならwhileを選びましょう。

**ループを逆順に回すにはどうすればよいですか？**

コレクションなら reversed(items)、数字なら range(n - 1, -1, -1) を使います。reversed はリストをコピーせず、後ろから読み進めます。

**Pythonにswitch文はありますか？**

独立したswitch文はありません。その役割は if/elif の連なりと、Python 3.10で導入された match/case が担います。matchはリストや辞書を形で分解し、値を取り出すこともできるため、より多くのことができます。

**ループと内包表記のどちらが速いですか？**

[x * 2 for x in items] のような内包表記は、同じ処理をappendで書いたループより少し速く、短く書けます。複数の条件を含む複雑な処理は、通常のループの方が読みやすいでしょう。

**二重ループを一度に抜けるにはどうすればよいですか？**

breakは内側のループだけを抜けます。ループを関数に入れ、returnで抜けるのが簡単です。


---
Source: Skillaria.Top (https://skillaria.top)
