[解決!Python]while文やfor文で無限ループを記述するには解決!Python

Pythonのwhile文を使って無限ループを記述する方法やその際の注意点、for文と無限イテレータを使って無限ループを記述する方法を紹介する。

» 2023年12月01日 05時00分 公開
[かわさきしんじDeep Insider編集部]

この記事は会員限定です。会員登録(無料)すると全てご覧いただけます。

「解決!Python」のインデックス

連載目次

* 本稿は2021年10月19日に公開された記事をPython 3.12.0で動作確認したものです(確認日:2023年12月1日)。


# 処理を5回行うまではループを続ける
cnt = 0
while True:
    print(cnt)  # 何らかの処理
    cnt += 1
    if cnt >= 5:
        break

# 無限ループでキューから値を取り出す
import time
from queue import Queue
from threading import Thread

def do_in_thread(q):
    while True:
        item = q.get(block=True)
        if not item:  # 取り出した要素が偽と見なされる値(空文字列など)であれば
            break  # 無限ループを終了
        print(item)
    print('out while loop')

# 以下の書き方も考えられる
#def do_in_thread(q):
#    item = q.get(block=True)
#    while item:
#        print(item)
#        item = q.get(block=True)
#    print('out while loop')

q = Queue()
th = Thread(target=do_in_thread, args=[q])
th.start()

for item in ['foo', 'bar', 'baz', '', 'hoge']:
    time.sleep(2)
    q.put(item)

# for文を使った無限ループ
from itertools import count, cycle, repeat

for num in count():
    print(num)
    if num >= 4:
        break

for idx, item in enumerate(cycle(['foo', 'bar', 'baz'])):
    print(item)
    if idx >= 4:
        break

for item in repeat('foo', 4):
    print(item)


無限ループとは

 while文は何らかの条件が成立している間、特定の処理を実行し続ける。「条件が成立」するとは、その式の評価結果が真(True)となることだ。そのため、条件にTrueを指定すると、while文の本体が無限に実行されることになる。このため、Pythonでは「while True:」で始まるwhile文を「無限ループ」と呼ぶことがよくある。

while True# 条件がTrue、つまり常に成立するので
    pass  # この行を無限に実行し続ける


 無限ループは本当に無限にループを実行するのが目的ではなく、ループの中で特定の条件が成立したら、ループを終了させるようなコードを書く。以下は変数cntの値が5以上になったらループを終了する無限ループだ。

cnt = 0
while True:
    print(cnt)  # 何らかの処理
    cnt += 1
    if cnt >= 5:
        break


while文を使った無限ループ

 上で見たように、while文の条件にTrueを指定して、その内部で何らかの処理を行った上で、ループを終わらせるかどうかの判定を行い、条件が成り立てばbreak文でループを終了させるのが無限ループの基本的な構造となる。無論、while文の条件にそうした記述が可能であれば、そうするのがよいだろう。上の無限ループは下のように書き直せる。

cnt = 0
while cnt < 5:
    print(cnt)
    cnt += 1


 また、条件にはTrueを指定せずとも、PythonでTrueと見なされる値を指定してもよい。例えば、以下のコードはメインスレッドでは2秒おきにキューに要素を追加して、もう1つのスレッドでは、キューから変数itemに要素を取り出し、その値を画面に出力するという処理を「while True:」で始まる無限ループの形で行っている(終了条件は変数itemに取り出した値が空文字列であること)。

import time
from queue import Queue
from threading import Thread

def do_in_thread(q: Queue):
    while True:
        item = q.get(block=True)
        if not item:  # 取り出した要素が偽と見なされる値(空文字列など)であれば
            break  # 無限ループを終了
        print(item)
    print('out while loop')

q = Queue()
th = Thread(target=do_in_thread, args=[q])
th.start()

for item in ['foo', 'bar', 'baz', '', 'hoge']:
    time.sleep(2)
    q.put(item)


 この例では、変数itemに取り出されるのは'foo'、'bar'、'baz'、''、'hoge'という文字列だ。Pythonでは空文字列(’’)は偽(False)として見なされるので、これをif文でチェックするようにしている。それ以外の文字列は全て真(True)となるので、上記のdo_in_thread関数は次のようにも書ける。

def do_in_thread(q: Queue):
    item = q.get(block=True)
    while item:
        print(item)
        item = q.get(block=True)
    print('out while loop')


 書き換えたコードでは「item = q.get(block=True)」行を2カ所に記述することになるが、if文での条件判断が不要になる。どちらが適切かの判断は難しいが、お好みの書き方をすればよいだろう。

 注意点としては、「while True:」による無限ループは特に何もなければ、その本体に記述したコードを無限に実行し続けるという点だ。何をいっているんだと思うかもしれないが、以下のコードを見てほしい(これは恣意(しい)的なコードである)。

from threading import Thread, Event
import time

def do_in_thread(ev):
    cnt = 0
    print('in thread')
    while True:
        print('in while loop')
        if ev.is_set():
            print(f'event fired: {cnt}')
            ev.clear()
            cnt += 1
            if cnt > 2:
                break
        else:
            time.sleep(1)
    print('out infinite loop')

ev = Event()
th = Thread(target=do_in_thread, args=[ev])
th.start()

for num in range(3):
    time.sleep(2)
    ev.set()


 これは上の例と同じくthreadingモジュールを使っている。メインスレッドでは、2秒に1回イベントを発生させる動作を3回行う。もう1つのスレッドでは、無限ループの形でイベントの発生をチェックして、イベントが発生したら「event fired: 0」などの出力を行う(イベントが発生していなければ、1秒スリープする)。

Copyright© Digital Advantage Corp. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。