Pythonのfor文で途中で抜ける方法【break文】

643, 2023-04-07

目次

Pythonのfor文で途中で抜けるには?

Pythonのfor文を使っているとfor文の途中でループから抜け出したい時があります。
そういうときはPythonではどうするのかと言うとbreak文を使うのが一般的です。

この記事ではPythonのfor文から途中で抜ける方法について具体的に解説します。
基礎となるbreak文の他、トリッキーなraiseを使った方法も解説します。

(^ _ ^)

ループからの脱出

break文でfor文から抜ける

Pythonのbreak文はループ文の中で使える文です。
これを使うとbreakを実行した直後にループから1つ抜けることが可能です。
具体的な使い方は以下になります。

for i in range(10):
    print(i)
    break

上記のfor文を見てみます。
for i in range(10):となってます。
これはループを10回回し、カウント変数はiでカウントするという意味です。
range(10)というのは数列を生成するコードで、ここで生成されていく数列がiに保存されていきます。

for文の中では

    print(i)
    break

と書いています。
これはカウント変数iprint()文で出力するという意味です。
その出力の直後にbreakでループから抜けています。
ループから抜けると当然、ループはそこでストップします。

ですのでカウント変数は0でストップするわけですね。
よって上記のコードの出力結果は

0

になります。

if文とbreak文を組み合わせる

では次のようなコードはどうでしょうか。

for i in range(10):
    print(i)
    if i == 4:
        break

実はbreak文はループの中で他の文と組み合わせて使うことができます。
上記の例ではif文と組み合わせています。

if i == 4:となっていますが、これはカウント変数i4になったら真になる条件文になっています。
真になるとif文の中身であるbreak文が実行されます。

よってこの上記のコードを実行すると

0
1
2
3
4

という出力結果になります。
カウント変数i4になったらループから脱出していますね。

このようにbreak文はif文などと組み合わせると複雑な条件でループから脱出できます。

入れ子になったfor文

break文は直近のfor文に対して実行されます。
これはどういうことでしょうか。

このbreak文の振る舞いを見るには入れ子になったfor文を見るのが手っ取り早いです。
下のコードを見てください。

for i in range(4):
    print('i', i)
    for k in range(4):
        print('k', k)
        break

入れ子になったfor文の振る舞いは大丈夫でしょうか?
上のコードは以下のコードに書き換えることができます。

for i in range(4):
    print('i', i)
    for k in range(4):
        print('k', k)

上記のコードはbreak文が入っていません。
ですので出力結果は以下になります。

i 0
k 0
k 1
k 2
k 3
i 1
k 0
k 1
k 2
k 3
i 2
k 0
k 1
k 2
k 3
i 3
k 0
k 1
k 2
k 3

入れ子になったfor文ではまず最初に外側のfor文が実行されます。
つまり

for i in range(4):
    print('i', i)
    for k in range(4):
        print('k', k)

であれば最初にfor i in range(4):のループが回ります。
子のループが回るとprint('i', i)が実行され、そのあとに2つ目のfor文に入っていきます。

2つ目(中側)のfor文ではfor k in range(4):となっていますので、ループが4回回ります。カウント変数はkです。
つまり外側のfor文でprint()が実行されると、中側のfor文が4回回ることになります。
それが外側のfor文のカウントが終わるまで、つまり4回まで続きます。
外側が4回、中川が4回なのであわせて4 * 4で16回のループが回ります。

これが入れ子になったfor文の動作です。
ではもう一度、最初のコードに戻ります。

for i in range(4):
    print('i', i)
    for k in range(4):
        print('k', k)
        break

上記のコードには中側のfor文の中にbreak文が入っています。
よって上記のコードを実行すると

i 0
k 0
i 1
k 0
i 2
k 0
i 3
k 0

という結果になります。
中側に書かれているbreak文は中側のfor文に対してのみ作用します。
つまり作用というのは中側のループから抜けるということです。外側のループからは抜けません。
外側のループは4回回りますので、中側のループから抜けても外側で4回ループすることになります。
よってカウント変数は上記のように出力されます。

このようにbreak文はbreak文が書かれているfor文に対してのみ作用します。

ネストされたfor文から一挙に脱出するには?

ネストされたfor文で内側のfor文内の条件によって外側のループからも抜けたいケースがあります。
こういう時はフラグを使うのが一般的です。

loop = True
for i in range(4):
    for k in range(4):
        loop = False
        break
    if not loop:
        break

print('done')

このコードではloopというフラグ変数を使っています。フラグとは真偽値であらわされた変数のことです。
中側のループでloop = FalseとやってTrueだったloopのフラグを折っています。折るとはFalseにすることです。
その直後、中側のループからbreakし、if not loop:に行きます。
そうするとloopFalseになっているのでこの条件式はTrueになり、if文の中のbreakが実行されます。
そうして外側のループから脱出し、めでたく入れ子のループから抜け出すことができます。

ちなみにC言語などはgoto文というのがあって入れ子になったループからも簡単に脱出できますが、Pythonにはないので代わりにraiseなどを代用することがあります。

raiseを使って入れ子のループから脱出するコードは以下になります。

try:
    for i in range(4):
        for k in range(4):
            print('raise!')
            raise Exception
except Exception:
    pass
print('done')

このコードの出力結果は以下になります。

raise!
done

raiseというのは例外を送出する文です。
例外というのはエラー処理に使われます。
たとえばファイルが無かったりとか、メモリが不足していたりとか、そう言う時に例外は使われます。
つまりraiseはネストされたfor文から抜け出すための文ではなく、これはトリッキーな使い方になります。
raiseが実行されるとそこからジャンプが発生して、try文のexceptにいきます。
raise ExceptionException例外を送出しているので、exceptでキャッチするときもExceptionを指定します。
送出された例外はキャッチしないとスタックトレースになってプログラムの実行が中断されます。

このコードの問題点は、ループの中で本来の意味での例外が発生したときにまぎらわしいことです。
ループの中でException例外が発生してもこのコードではなにも処理せずに通過させます。
なぜならネストされたループの脱出にExceptionを使っているからです。

この問題を解決するにはException例外を継承して独自例外を作り、その独自例外でジャンプするという方法があります。
この独自例外はループから脱出する場合にのみ使用する例外になります。

class Break(Exception):
    pass

しかし、これは可能なことは可能ですが、やっている人いるんでしょうか。
私も見かけたことありません。
お作法的にはあまり良くないと思うので、フラグを使う方を採用された方がいいかもしれません。

おわりに

今回はPythoのfor文から抜ける方法を解説しました。
break文を使えばループから脱出可能です。

(^ _ ^)

大脱走

(・ v ・)

さらばループよ



この記事のアンケートを送信する