Pythonで無限ループを作成する2つの方法を見てきました。
while 1:
do_something()
while True:
do_something()
これらの間に違いはありますか?一方はもう一方よりもPythonicですか?
基本的には問題ではありません。そのような細目は、何かが「Pythonic」であるかどうかには実際には影響しません。
ただし、雑学クイズに興味がある場合は、いくつかの違いがあります。
組み込みのブール型はPython 2. まで存在しなかったため、古いバージョンで実行することを目的としたコードはwhile 1:
フォームを使用する傾向があります。たとえば、標準ライブラリ。
TrueとFalseのビルトインは Python より前の予約語ではないので、それらの値を変更して割り当てることができます。これは、コードがTrue = 1
を実行できるため、上記の場合に役立ちます。下位互換性のためですが、名前True
は、使用するたびにグローバルディクショナリで検索する必要があることを意味します。
上記の制限により、2つのバージョンのコンパイル先のバイトコードはPython 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
_を使用しますが、これはもう少し明確です。
より一般的には、人々が書くwhile-breakループの多くはPythonは別のものである可能性があります。時々、人々が_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)
。
これは主にスタイルの問題だと思います。どちらも無限ループとして簡単に理解できるはずです。
ただし、個人的には2番目のオプションを好みます。これは、特にCのバックグラウンドを持たないプログラマーにとっては、理解するのに精神的なマイクロステップが少なくて済むためです。
最初のものは、True
がまだ定義されていない初期のバージョンでも機能します。
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)
有限時間で終了することが想定されているアルゴリズムがある場合は、これをお勧めします。これは、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番目のオプションは、True
がFalse
に割り当てられていない場合にのみ機能します。これは、Python 3:
>>> True = False
>>> True
False
より良い方法は、ループからの条件付きブレークを使用した「whileTrue」です。