Python で無限ループを作成する 2 つの方法を見てきました。
while 1: do_something()
while True: do_something()
これらの間に違いはありますか?一方は他方よりもPythonicですか?
Python で無限ループを作成する 2 つの方法を見てきました。
while 1:
do_something()
while True:
do_something()
これらの間に違いはありますか?一方は他方よりもPythonicですか?
基本的には問題ではありません。そのような細目は、何かが「pythonic」であるかどうかに実際には影響しません。
ただし、トリビアに興味がある場合は、いくつかの違いがあります。
組み込みのブール型は Python 2.3 まで存在しなかったため、古いバージョンで実行することを意図したコードはこの形式を使用する傾向がありますwhile 1:
。たとえば、標準ライブラリに表示されます。
True および False ビルトインは、Python 3 より前では予約語ではないため、値を変更して割り当てることができました。True = 1
コードは下位互換性を維持できるため、これは上記のケースに役立ちますが、名前True
を使用するたびにグローバル ディクショナリで名前を検索する必要があることを意味します。
上記の制限により、Python 2 では使用できない定数整数の最適化があるため、2 つのバージョンがコンパイルされるバイトコードは異なりますTrue
。Python は をコンパイルするときに1
常に非ゼロであることを認識できるため、条件付きジャンプを削除し、定数をまったくロードしません。
>>> import dis
>>> def while_1():
... while 1:
... pass
...
>>> def while_true():
... while True:
... pass
...
>>> dis.dis(while_1)
2 0 SETUP_LOOP 5 (to 8)
3 >> 3 JUMP_ABSOLUTE 3
6 POP_TOP
7 POP_BLOCK
>> 8 LOAD_CONST 0 (None)
11 RETURN_VALUE
>>> dis.dis(while_true)
2 0 SETUP_LOOP 12 (to 15)
>> 3 LOAD_GLOBAL 0 (True)
6 JUMP_IF_FALSE 4 (to 13)
9 POP_TOP
3 10 JUMP_ABSOLUTE 3
>> 13 POP_TOP
14 POP_BLOCK
>> 15 LOAD_CONST 0 (None)
18 RETURN_VALUE
そのためwhile True:
、少し読みやすく、while 1:
古いバージョンの Python に少し優しくなっています。最近では Python 2.2 で実行する必要がなくなったり、ループのバイトコード数を気にする必要がなくなったりするため、前者の方がわずかに適しています。
最も Pythonic な方法は、常に最も読みやすいものになります。使用するwhile True:
それは本当に問題ではありません。どちらも読みにくく理解しにくいわけではありませんが、個人的には常に を使用しますwhile True
が、これはもう少し明示的です。
より一般的に言えば、人々が Python で書いた非常に多くの while-break ループは、別のものである可能性があります。時々、人々が を書いているのを見かけますがi = 0; while True: i += 1 ...
、これは に置き換えることができ、これを書くことができるときにfor i in itertools.count()
書いている人もいます。これは、学習が必要ですが、ボイラープレートが少なく、ばかげた間違いをする機会が少なくなります。while True: foo = fun() if foo is None: break
for foo in iter(fun, None)
ない。
どちらも、コードをスキャンして を探す必要があることを意味しbreak
、停止条件が属する場所を確認することができません。
私は可能な限りこの種のことを回避しようとします。それが不可能な場合は、コードが次のように語るようにします。
while not found_answer:
check_number += 1
if check_number == 42:
found_answer = True
編集:上記の「回避」という言葉は十分に明確ではなかったようです. 基本的に無限ループを使用し、ループ内のどこかから離れる ( を使用するbreak
)ことは、通常、完全に避ける必要があります。時々それは不可能です。その場合、私は上記のコードのようなものを使用するのが好きですが、それでも同じ概念を表しています.上記の コードは妥協にすぎません.関数を呼び出さないのと同じようにdo_something_with_args(*args)
。
IMO の 2 番目のオプションはより明白です。
を取り除き、よりコンパクトなコードを書くことができればwhile
、それはより Pythonic になるかもしれません。
例えば:
# Get the even numbers in the range 1..10
# Version 1
l = []
n = 1
while 1:
if n % 2 == 0: l.append(n)
n += 1
if n > 10: break
print l
# Version 2
print [i for i in range(1, 11) if i % 2 == 0]
# Version 3
print range(2, 11, 2)
これは主にスタイルの問題だと思います。どちらも無限ループとして簡単に理解できるはずです。
ただし、個人的には2番目のオプションを好みます。これは、特にCのバックグラウンドを持たないプログラマーにとっては、理解するのに精神的なマイクロステップが少なくて済むためです。
True
最初のものは、まだ定義されていない初期バージョンでも機能します。
有限時間で終了すると思われるアルゴリズムがある場合は、これをお勧めします。これは常により安全ですwhile True
。
maxiter = 1000
for i in xrange(maxiter):
# your code
# on success:
break
else:
# that algorithm has not finished in maxiter steps! do something accordingly
2番目の式はより明示的であり、したがってよりpythonicだと思います。
これは単にスタイルの問題であり、プログラミングの初心者なら誰でもどちらのオプションも理解できます。
しかし、2 番目のオプションは、 Python 3 まで可能だった が にTrue
割り当てられていない場合にのみ機能します。False
>>> True = False
>>> True
False
より良い方法は、条件付きでループから抜け出す "while True" です。