ループ

コードを書いていると、同じアクションを繰り返す必要がある場面によく遭遇します——1 から 100 までの数値を出力する、リストのすべての要素を処理する、有効な回答が得られるまでユーザーに入力を求め続ける、などです。

100 個の数値に対して 100 行の print() を書くのは非現実的です。そこで登場するのがループです。Python には 2 種類のループがあります:


for ループの基本

for ループは Python で最もよく使われるループです。その核となる考え方は:シーケンスから要素を 1 つずつ取り出し、毎回同じコードブロックを実行することです。

基本構文:

PYTHON
for variable in sequence:
    code to repeat

変数にはシーケンス内の各要素が代入され、インデントされたブロックが各要素に対して実行されます。

例:リストと文字列の反復(⭐)

PYTHON
# リストの反復
fruits = ["apple", "banana", "orange", "grape"]
for fruit in fruits:
    print(f"I like {fruit}")

print("---")

# 文字列の反復 — 1 文字ずつ
for char in "Python":
    print(char)
▶ 試してみよう

出力:

TEXT
I like apple
I like banana
I like orange
I like grape
---
P
y
t
h
o
n
💡 命名のヒント:ループ変数は単数形にしましょう。リストが fruits なら fruit を、students なら student を使います。コードが自然言語のように読めます。


range() 関数 — 数値シーケンスの生成

決まった回数だけ繰り返す必要がある場合、range() が最適です。

range() には 3 つの形式があります:

構文 意味 結果
range(stop) 0 → stop-1 range(5) 0,1,2,3,4
range(start, stop) start → stop-1 range(2, 6) 2,3,4,5
range(start, stop, step) ステップ付き range(1, 10, 2) 1,3,5,7,9

注意:range() は stop 値を含みません——スライスと同じで「含まずに」です。

例:range でループ回数を制御(⭐)

PYTHON
# 1 から 5 まで出力
for i in range(1, 6):
    print(f"Loop {i}")

print("---")

# ステップ 2:0 から 10 までの偶数を出力
for i in range(0, 11, 2):
    print(i, end=" ")  # end=" " で改行を防止
# 出力:0 2 4 6 8 10
▶ 試してみよう

例:インデックスを使った反復(⭐⭐)

PYTHON
students = ["Alice", "Bob", "Charlie", "Diana"]

# インデックスと要素の両方を取得
for i in range(len(students)):
    print(f"Student {i + 1}: {students[i]}")
▶ 試してみよう

出力:

TEXT
Student 1: Alice
Student 2: Bob
Student 3: Charlie
Student 4: Diana
💡 よりエレガントな方法:Python でインデックスと要素の両方が必要な場合は、enumerate() を使います。後のレッスンで説明します。


while ループ

whilefor の違い:for はループ回数がわかっている場合に使い、while は停止条件だけがわかっている場合に使います

基本構文:

PYTHON
while condition:
    code to repeat

各反復の前に条件がチェックされます。True ならコードブロックが実行され、再度条件がチェックされます……False になるまで続きます。

例:カウントダウン(⭐)

PYTHON
count = 5
while count > 0:
    print(f"Countdown: {count}")
    count -= 1  # 毎回 1 ずつ減らす — 非常に重要!

print("Launch!")
▶ 試してみよう

出力:

TEXT
Countdown: 5
Countdown: 4
Countdown: 3
Countdown: 2
Countdown: 1
Launch!
⚠️ 無限ループ警告:count -= 1 を忘れると、条件 count > 0 が常に True になり、プログラムは強制終了するまで永久に実行されます。while ループを書くときは、条件がいつか False になることを常に確認してください。

例:典型的な while の使い方 — 特定の値になるまで(⭐⭐)

PYTHON
# 1 未満になるまで半分にし続ける
num = 100
while num >= 1:
    print(num, end=" → ")
    num /= 2
# 出力:100 → 50.0 → 25.0 → 12.5 → 6.25 → 3.125 → 1.5625 → 0.78125
▶ 試してみよう

これは while の強みを示しています:必要な反復回数を事前に知る必要がなく、いつ停止するかだけがわかっていればよいのです。


breakcontinue — ブレーキとスキップ

break — ループを即座に終了

条件が満たされると、breakループ全体から抜け出し、残りの反復を無視します。

continue — 現在の反復をスキップ

条件が満たされると、continue現在の反復の残りをスキップし、次の反復に移ります。

例:break vs continue(⭐)

PYTHON
print("=== break example ===")
for i in range(1, 10):
    if i == 5:
        break  # 5 に達したらループを終了
    print(i, end=" ")
# 出力:1 2 3 4

print("\n=== continue example ===")
for i in range(1, 10):
    if i == 5:
        continue  # 5 をスキップして残りを続行
    print(i, end=" ")
# 出力:1 2 3 4 6 7 8 9
▶ 試してみよう

例:break の実践 — 検索して停止(⭐⭐)

PYTHON
# リスト内の最初の偶数を検索
numbers = [3, 7, 9, 2, 5, 8, 1]

for num in numbers:
    if num % 2 == 0:
        print(f"Found first even number: {num}")
        break  # 見つかったら検索を停止
else:
    print("No even numbers in the list")  # この else は for ループに属する
▶ 試してみよう

例:continue の実践 — 有効データのみ処理(⭐⭐)

PYTHON
# 正の数のみ処理、負の数とゼロはスキップ
data = [3, -5, 0, 8, -2, 7, 0, 4]
positive_sum = 0

for num in data:
    if num <= 0:
        continue  # 無効なデータをスキップ
    positive_sum += num

print(f"Sum of positive numbers: {positive_sum}")  # 出力:22 (3+8+7+4)
▶ 試してみよう

for-elsewhile-else — 「正常完了ボーナス」

これは Python のユニークな構文機能であり、他の多くの言語にはありません。

else ブロックはループが正常に完了した場合(break によって中断されなかった場合)に実行されます。次のように考えてください:「ループが中断されなかった場合、このボーナスコードを実行する」。

例:素数判定(⭐⭐)

PYTHON
num = 17

for i in range(2, num):
    if num % i == 0:
        print(f"{num} is not prime, divisible by {i}")
        break
else:
    print(f"{num} is prime!")  # break が発生しなかった場合のみ実行
▶ 試してみよう

この例では:

💡 多くの初心者は for-else を直感的でないと感じます。次のように覚えてください:else「break が発生しなかった場合、…」 を意味します。


ネストしたループ

ループの中に別のループがあるものをネストしたループと呼びます。外側のループの各反復ごとに、内側のループが完全に 1 回実行されます。

例:九九の表(⭐⭐)

PYTHON
for i in range(1, 10):         # 外側のループ:行
    for j in range(1, i + 1):  # 内側のループ:列
        print(f"{j}×{i}={i*j}", end="\t")
    print()  # 各行の後に改行
▶ 試してみよう

出力:

TEXT
1×1=1
1×2=2    2×2=4
1×3=3    2×3=6    3×3=9
1×4=4    2×4=8    3×4=12   4×4=16
1×5=5    2×5=10   3×5=15   4×5=20   5×5=25
1×6=6    2×6=12   3×6=18   4×6=24   5×6=30   6×6=36
1×7=7    2×7=14   3×7=21   4×7=28   5×7=35   6×7=42   7×7=49
1×8=8    2×8=16   3×8=24   4×8=32   5×8=40   6×8=48   7×8=56   8×8=64
1×9=9    2×9=18   3×9=27   4×9=36   5×9=45   6×9=54   7×9=63   8×9=72   9×9=81
⚠️ パフォーマンスのヒント: 総実行回数 = 外側の回数 × 内側の回数。N レベルのネストは指数関数的な増加を意味します。大規模データセットを扱う場合は、3 レベル以上のネストに注意してください。

例:break は現在のレベルにのみ影響(⭐⭐)

PYTHON
for i in range(1, 4):
    for j in range(1, 10):
        if j > i:
            break  # 内側のループのみを break
        print(f"({i},{j})", end=" ")
    print()
▶ 試してみよう

出力:

TEXT
(1,1)
(2,1) (2,2)
(3,1) (3,2) (3,3)

総合的な例

例 1:数当てゲーム(⭐⭐)

システムが 1~100 のランダムな数を生成します。プレイヤーが推測し、システムがヒント(「大きすぎる」または「小さすぎる」)を出し、正解するまで続けます。

PYTHON
import random

# ランダムなターゲットを生成
target = random.randint(1, 100)
attempts = 0

print("🎯 Guess the Number! I'm thinking of a number between 1 and 100.")

while True:  # 無限ループ、break で終了
    try:
        guess = int(input("Enter your guess: "))
    except ValueError:
        print("Please enter a valid number!")
        continue

    attempts += 1

    if guess < target:
        print("Too low, try higher!")
    elif guess > target:
        print("Too high, try lower!")
    else:
        print(f"🎉 Congratulations! It's {target}!")
        print(f"You guessed it in {attempts} attempts.")
        break  # 正解したらループを終了
▶ 試してみよう

例 2:パスワード強度チェッカー(⭐⭐⭐)

ユーザーのパスワードをチェックし、強度をスコアリングします。

PYTHON
password = input("Enter your password: ")
score = 0
feedback = []

# 1. 長さをチェック
if len(password) >= 8:
    score += 1
else:
    feedback.append("❌ Password is less than 8 characters")

# 2. 文字種をチェック
has_upper = False
has_lower = False
has_digit = False
has_special = False
special_chars = "!@#$%^&*"

for char in password:
    if char.isupper():
        has_upper = True
    elif char.islower():
        has_lower = True
    elif char.isdigit():
        has_digit = True
    elif char in special_chars:
        has_special = True

# チェックに基づいてスコアリング
checks = [has_upper, has_lower, has_digit, has_special]
score += sum(checks)

if not has_upper:
    feedback.append("❌ Missing uppercase letter")
if not has_lower:
    feedback.append("❌ Missing lowercase letter")
if not has_digit:
    feedback.append("❌ Missing digit")
if not has_special:
    feedback.append("❌ Missing special character")

# 3. 結果を出力
print(f"\nPassword strength: {score}/5")
if feedback:
    print("Suggestions:")
    for item in feedback:
        print(f"  {item}")
else:
    print("🎉 Strong password!")
▶ 試してみよう

よくあるユースケース

シナリオ 推奨ループ 備考
リスト/タプル/セットの反復 for 要素を 1 つずつ処理
辞書のキーと値のペアの反復 for .items() を使用
N 回の繰り返し for + range() 固定回数の反復
条件を満たすまで while 反復回数が不明
ファイルを EOF まで読み込み forwhile ファイルオブジェクトは反復可能
ユーザー入力の検証 while + break 有効な入力になるまでループ
無限ループ(サーバー、ゲームループ) while True break で終了

❓ よくある質問

Q forwhile はいつ使い分ければよいですか?
A 反復回数がわかっている場合は for を使います(リスト/range/文字列の反復)。停止条件がわかっている場合は while を使います(入力を待つ、値に近づく)。多くの場合、互いに置き換え可能ですが、適切に選ぶとコードが明確になります。
⚠️ Q:for i in range(len(list)) は Python らしいですか? A:あまり Python らしくありません。Python は直接反復を好みます:for item in list。インデックスが具体的に必要な場合のみ range(len(...)) を使います。そしてその場合でも、enumerate() の方がよりエレガントです。

Q ネストしたループが多すぎる場合はどうすればよいですか?
A 3 レベルを超えるネストは可読性を損なう。解決策:内側のループを関数に抽出する、itertools で組み合わせを生成する、またはアルゴリズムを見直す。

📖 まとめ


📝 練習問題

⭐ 練習 1:偶数の和

for ループと range() を使って、1 から 100 までのすべての偶数の合計を計算してください。

ヒント:range(2, 101, 2) で一度に取得できます。

⭐⭐ 練習 2:フィボナッチ数列

定義:最初の 2 つの数は 1 で、後続の各数は前の 2 つの数の和です。 数列:1, 1, 2, 3, 5, 8, 13, 21, ...

while ループを使って、1000 を超えないすべてのフィボナッチ数を出力してください。

ヒント:3 つの変数 a, b で現在の 2 つの数を保持し、a + b で次の数を計算してシフトします。

⭐⭐⭐ 練習 3:簡易電卓

2 つの数値と演算子(+, -, *, /)を繰り返し尋ね、結果を出力するプログラムを書いてください。 q を入力すると終了します。

要件:

100%