Pythonでfor文のループを抜ける方法!breakやcontinueを使った書き方

Pythonでfor文のループを抜ける方法!breakやcontinueを使った書き方 プログラミングの疑問解決

Pythonでのプログラミングにおいて、ループ処理は最も基本的かつ重要な制御構造の一つです。

しかし、すべての要素を最後まで処理する必要がない場合や、特定の条件下で一部の処理をスキップしたい場合はどうすればよいでしょうか。

そんな時に活躍するのが、ループ制御文の「break」と「continue」です。

この記事では、Pythonのfor文やwhile文で使えるbreak文とcontinue文について、初心者の方でも理解しやすいように、実際に動作するコード例を交えながら詳しく解説していきます。

【本記事の信頼性】

  • 執筆者は元エンジニア
  • 大手プログラミングスクールのWebディレクター兼ライターを経験
  • 自らも地元密着型のプログラミングスクールを運営
未経験者におすすめの
プログラミングスクール
■Webエンジニアの育成に特化
■自社開発企業への転職成功率がダントツ
■ハイスキルを求める人に最適
■サポートは半永久的
■単価80万円以上の講師陣
■AWSやJavaに強い
■受講料完全無料
■最短1か月で卒業
■教室への通学も可能

Pythonのループ処理はforかwhile

Pythonでは、同じ処理を繰り返し実行したい場合にループ処理を使います。

ループ処理には主に「for文」「while文」の2種類があり、それぞれ異なる場面で活用されます。

まずfor文は、リストやタプル、文字列などのシーケンス型のオブジェクトに対して、要素を一つずつ取り出しながら処理を実行します。
決まった回数だけ繰り返したい場合や、コレクションの要素すべてに対して処理を行いたい場合に最適です。

# リストの要素を順番に表示
fruits = ['apple', 'banana', 'orange']
for fruit in fruits:
    print(fruit)

# 実行結果
# apple
# banana
# orange

一方while文は、条件式が真(True)である限り処理を繰り返します。
繰り返し回数が事前に決まっていない場合や、特定の条件を満たすまで処理を続けたい場合に便利でしょう。

# カウンターが5になるまで繰り返す
counter = 0
while counter < 5:
    print(f"カウント: {counter}")
    counter += 1

# 実行結果
# カウント: 0
# カウント: 1
# カウント: 2
# カウント: 3
# カウント: 4

ループ処理は便利ですが、時には途中で処理を中断したり、特定の回だけスキップしたりしたいケースもあります。

そんな時に活躍するのが、これから紹介するbreakやcontinue文なのです。

breakを使ってfor文を抜ける書き方

break文は、ループを完全に終了させたい時に使用します。
特定の条件を満たした時点で、それ以降の繰り返し処理を実行せずに、ループから抜け出すことができます。

基本的な使い方を見てみましょう。

以下の例では、数値のリストから5を見つけたらループを終了します。

numbers = [1, 3, 5, 7, 9, 11]
for num in numbers:
    if num == 5:
        print("5を見つけました!ループを終了します")
        break
    print(f"現在の数値: {num}")

print("ループ処理が終了しました")

# 実行結果
# 現在の数値: 1
# 現在の数値: 3
# 5を見つけました!ループを終了します
# ループ処理が終了しました

実際の開発では、ユーザー入力の検証や、条件に合うデータの検索など、様々な場面でbreak文が活用されます。

例えば、パスワードの入力を3回まで許可するプログラムを作ってみましょう。

correct_password = "python123"
max_attempts = 3

for attempt in range(max_attempts):
    password = input(f"パスワードを入力してください({attempt + 1}/{max_attempts}回目): ")
    
    if password == correct_password:
        print("ログインに成功しました!")
        break
    else:
        print("パスワードが間違っています")
        
        if attempt == max_attempts - 1:
            print("ログインに失敗しました。アカウントがロックされました")

# 実行結果(正しいパスワードを2回目に入力した場合)
# パスワードを入力してください(1/3回目): wrong
# パスワードが間違っています
# パスワードを入力してください(2/3回目): python123
# ログインに成功しました!

ネストされたループ(ループの中にループがある構造)では、break文は最も内側のループのみを終了させます。

すべてのループを抜けたい場合は、フラグ変数を使うか、関数化してreturn文を使う方法があります。

# ネストされたループでのbreak文の動作
found = False
for i in range(3):
    for j in range(3):
        print(f"i={i}, j={j}")
        if i == 1 and j == 1:
            print("条件を満たしました。内側のループを終了")
            found = True
            break
    if found:
        print("外側のループも終了")
        break

# 実行結果
# i=0, j=0
# i=0, j=1
# i=0, j=2
# i=1, j=0
# i=1, j=1
# 条件を満たしました。内側のループを終了
# 外側のループも終了

continueを使ってfor文を抜ける書き方

continue文は、現在の反復(イテレーション)の残りの処理をスキップし、次の反復に進みたい時に使用します。

break文とは異なり、ループ自体は継続されるため、特定の条件の時だけ処理をスキップしたい場合に便利でしょう。

基本的な使い方を確認するため、偶数だけを表示するプログラムを例に説明します。

# 1から10までの偶数のみを表示
for num in range(1, 11):
    if num % 2 != 0:  # 奇数の場合
        continue  # 以降の処理をスキップして次の数値へ
    print(f"偶数: {num}")

# 実行結果
# 偶数: 2
# 偶数: 4
# 偶数: 6
# 偶数: 8
# 偶数: 10

continue文は、データの前処理や条件に合わないデータの除外など、実務でも頻繁に使用されます。

例えば、CSVファイルの処理で空行や無効なデータをスキップする場合を見てみましょう。

# データリストから有効なメールアドレスのみを処理
email_list = [
    "user1@example.com",
    "",  # 空のデータ
    "invalid-email",  # 無効な形式
    "user2@example.com",
    "user3@",  # 不完全なアドレス
    "user4@example.com"
]

valid_emails = []
for email in email_list:
    # 空文字列をスキップ
    if not email:
        print(f"空のデータをスキップしました")
        continue
    
    # @マークが含まれていない場合をスキップ
    if "@" not in email:
        print(f"無効なメール形式をスキップ: {email}")
        continue
    
    # ドメイン部分が不完全な場合をスキップ
    if not email.split("@")[-1]:
        print(f"ドメインが不完全: {email}")
        continue
    
    # 有効なメールアドレスのみリストに追加
    valid_emails.append(email)
    print(f"有効なメールアドレス: {email}")

print(f"\n処理結果: {len(valid_emails)}件の有効なメールアドレスを検出")

# 実行結果
# 有効なメールアドレス: user1@example.com
# 空のデータをスキップしました
# 無効なメール形式をスキップ: invalid-email
# 有効なメールアドレス: user2@example.com
# ドメインが不完全: user3@
# 有効なメールアドレス: user4@example.com
# 
# 処理結果: 3件の有効なメールアドレスを検出

continue文を使う際の注意点として、continue文より後に書かれたコードは実行されません。
そのため、重要な処理はcontinue文の前に配置する必要があるでしょう。

# continue文の位置による動作の違い
total = 0
numbers = [1, 2, 3, 4, 5]

for num in numbers:
    # continue前の処理は実行される
    print(f"処理中の数値: {num}")
    
    if num == 3:
        continue
    
    # continue後の処理は、num==3の時はスキップされる
    total += num
    print(f"  合計に追加しました(現在の合計: {total})")

print(f"\n最終的な合計: {total}")

# 実行結果
# 処理中の数値: 1
#   合計に追加しました(現在の合計: 1)
# 処理中の数値: 2
#   合計に追加しました(現在の合計: 3)
# 処理中の数値: 3
# 処理中の数値: 4
#   合計に追加しました(現在の合計: 7)
# 処理中の数値: 5
#   合計に追加しました(現在の合計: 12)
# 
# 最終的な合計: 12

breakとcontinueを組み合わせることで、より複雑な制御フローも実現できます。

以下の例では、特定の条件でスキップしつつ、別の条件でループを終了させています。

# 素数を探すプログラム(10個見つけたら終了)
primes = []
num = 2

while len(primes) < 10:
    # 素数判定
    is_prime = True
    
    # 2から平方根までの数で割り切れるかチェック
    for i in range(2, int(num ** 0.5) + 1):
        if num % i == 0:
            is_prime = False
            break
    
    # 素数でない場合は次の数へ
    if not is_prime:
        num += 1
        continue
    
    # 素数をリストに追加
    primes.append(num)
    print(f"{len(primes)}個目の素数: {num}")
    
    # 10個見つけたらループ終了
    if len(primes) == 10:
        break
    
    num += 1

print(f"\n最初の10個の素数: {primes}")

# 実行結果
# 1個目の素数: 2
# 2個目の素数: 3
# 3個目の素数: 5
# 4個目の素数: 7
# 5個目の素数: 11
# 6個目の素数: 13
# 7個目の素数: 17
# 8個目の素数: 19
# 9個目の素数: 23
# 10個目の素数: 29
# 
# 最初の10個の素数: [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]

breakやcontinueを使用する際に注意すべきこと

breakやcontinueは便利なものの、使い方を誤るとバグの原因になったり、コードの可読性を損なったりする可能性があります。

ここでは、breakとcontinueという制御文を使用する際の重要な注意点を解説していきます。

無限ループに陥らないようにする

while文でcontinueを使用する際、ループカウンターの更新を忘れると無限ループになってしまいます。
必ずcontinueの前でカウンターを更新するか、条件を適切に設定してください。

# 悪い例:無限ループになるコード
count = 0
while count < 5:
    if count == 2:
        continue  # countが更新されないため、永遠に2のまま
    print(count)
    count += 1  # この行は実行されない

# 良い例:正しく動作するコード
count = 0
while count < 5:
    if count == 2:
        count += 1  # continue前に更新
        continue
    print(count)
    count += 1

# 実行結果
# 0
# 1
# 3
# 4

ネストしたループでの挙動を理解する

breakは最も内側のループのみを終了させます。
複数のループをまとめて抜けたい場合は、フラグ変数を使うか、関数化してreturnを使う方法を検討しましょう。

# フラグ変数を使った例
def find_target():
    target = 15
    found = False
    
    for i in range(5):
        for j in range(5):
            value = i * j
            print(f"i={i}, j={j}, value={value}")
            
            if value == target:
                print(f"目標値{target}を発見!")
                found = True
                break
        
        if found:
            break
    
    return found

# 関数とreturnを使った例(より簡潔)
def find_target_with_return():
    target = 15
    
    for i in range(5):
        for j in range(5):
            value = i * j
            print(f"i={i}, j={j}, value={value}")
            
            if value == target:
                print(f"目標値{target}を発見!")
                return True
    
    return False

# どちらの方法でも同じ結果が得られる
result = find_target_with_return()

elseとの組み合わせに注意

Pythonのfor文やwhile文には、elseを付けることができます。
このelseは、ループが正常に終了した場合(breakで中断されなかった場合)にのみ実行されるため、動作を正しく理解することが重要です。

# break文とelse節の組み合わせ
def search_number(numbers, target):
    for num in numbers:
        if num == target:
            print(f"{target}が見つかりました!")
            break
    else:
        # breakが実行されなかった場合のみ実行される
        print(f"{target}は見つかりませんでした")

# テスト
search_number([1, 3, 5, 7, 9], 5)  # 見つかる場合
search_number([1, 3, 5, 7, 9], 6)  # 見つからない場合

# 実行結果
# 5が見つかりました!
# 6は見つかりませんでした

コードの可読性を保つ

breakやcontinueを過度に使用すると、コードの流れが追いにくくなります。
特に、深くネストしたループや複雑な条件分岐と組み合わせる場合は、コメントを追加したり、処理を関数に分割したりすることを検討してください。

# 可読性の低い例
def process_data_poor(data):
    for item in data:
        if not item:
            continue
        if item < 0:
            continue
        if item > 100:
            break
        if item % 2 == 0:
            continue
        # 実際の処理
        print(item)

# 可読性の高い例
def is_valid_item(item):
    """有効なアイテムかどうかを判定"""
    if not item or item < 0:
        return False
    if item % 2 == 0:  # 偶数は除外
        return False
    return True

def process_data_better(data):
    """100を超える値が現れるまで、有効な奇数を処理"""
    for item in data:
        if item > 100:
            print("100を超える値を検出。処理を終了します")
            break
        
        if is_valid_item(item):
            print(f"処理対象: {item}")

# テスト
test_data = [0, -1, 3, 4, 7, 8, 15, 101, 20]
process_data_better(test_data)

# 実行結果
# 処理対象: 3
# 処理対象: 7
# 処理対象: 15
# 100を超える値を検出。処理を終了します

パフォーマンスへの影響を考慮

大量のデータを処理する場合、不適切なbreak文やcontinue文の使用はパフォーマンスに影響を与える可能性があります。

条件を事前にフィルタリングできる場合は、そちらの方法も検討しましょう。

import time

# 大量のデータでのパフォーマンス比較
large_data = list(range(1000000))

# continue文を使った方法
start_time = time.time()
result1 = []
for num in large_data:
    if num % 2 == 0:
        continue
    if num > 50000:
        break
    result1.append(num)
end_time = time.time()
print(f"continue文使用: {end_time - start_time:.4f}秒")

# リスト内包表記を使った方法
start_time = time.time()
result2 = [num for num in large_data if num % 2 != 0 and num <= 50000]
end_time = time.time()
print(f"リスト内包表記: {end_time - start_time:.4f}秒")

# フィルタリングを事前に行う方法
start_time = time.time()
filtered_data = filter(lambda x: x % 2 != 0, large_data)
result3 = []
for num in filtered_data:
    if num > 50000:
        break
    result3.append(num)
end_time = time.time()
print(f"事前フィルタリング: {end_time - start_time:.4f}秒")

これらの注意点を理解し、適切に使い分けることで、より保守性の高い、効率的なコードを書くことができます。

まとめ

Pythonのループ制御文であるbreakとcontinueは、プログラムの流れを柔軟に制御するための重要な機能です。

break文はループを完全に終了させ、continue文は現在の反復をスキップして次の反復に進む動作をします。

これらの制御文を適切に使い分けることで、より効率的で読みやすいコードを書くことができるでしょう。

Follow me!

PAGE TOP