PythonでDO-whileループをエミュレート?
-
09-09-2019 - |
質問
私は、PythonプログラムでDO-whileループをエミュレートする必要があります。残念ながら、以下の簡単なコードは動作しません。
list_of_ints = [ 1, 2, 3 ]
iterator = list_of_ints.__iter__()
element = None
while True:
if element:
print element
try:
element = iterator.next()
except StopIteration:
break
print "done"
代わりに"1,2,3、行って"、それは次の出力を印刷します:
[stdout:]1
[stdout:]2
[stdout:]3
None['Traceback (most recent call last):
', ' File "test_python.py", line 8, in <module>
s = i.next()
', 'StopIteration
']
私は「停止の繰り返し」例外をキャッチしている間を破るために何ができます ループ正しく?
このようなことが必要とされる理由の一例を擬似コードとして以下に示されている。
ステートマシンます:
s = ""
while True :
if state is STATE_CODE :
if "//" in s :
tokens.add( TOKEN_COMMENT, s.split( "//" )[1] )
state = STATE_COMMENT
else :
tokens.add( TOKEN_CODE, s )
if state is STATE_COMMENT :
if "//" in s :
tokens.append( TOKEN_COMMENT, s.split( "//" )[1] )
else
state = STATE_CODE
# Re-evaluate same line
continue
try :
s = i.next()
except StopIteration :
break
解決
私は、あなたがやろうとしているのかわからないです。あなたはこのように、DO-whileループを実装することができます:
while True:
stuff()
if fail_condition:
break
それともます:
stuff()
while not fail_condition:
stuff()
あなたは、リスト内のものを印刷するdo-while文を使用しようとして何をしているのか?理由だけではなく、使用しています:
for i in l:
print i
print "done"
アップデートます:
ですから、行のリストを持っているのですか?そして、あなたはそれを反復処理を維持したいですか?いかがます:
for s in l:
while True:
stuff()
# use a "break" instead of s = i.next()
は、あなたが望むものに近いもののように見えることありますか?あなたのコード例では、それは次のようになります:
for s in some_list:
while True:
if state is STATE_CODE:
if "//" in s:
tokens.add( TOKEN_COMMENT, s.split( "//" )[1] )
state = STATE_COMMENT
else :
tokens.add( TOKEN_CODE, s )
if state is STATE_COMMENT:
if "//" in s:
tokens.append( TOKEN_COMMENT, s.split( "//" )[1] )
break # get next s
else:
state = STATE_CODE
# re-evaluate same line
# continues automatically
他のヒント
ここでDO-whileループをエミュレートするための非常にシンプルな方法です
condition = True
while condition:
# loop body here
condition = test_loop_condition()
# end of loop
DO-whileループの主要な機能は、ループ本体が常に少なくとも一度実行されること、及び条件はループ本体の底部に評価されることです。ここでの制御構造のショーは、例外やbreak文を必要とせず、これらの両方を達成します。これは、1つの余分なブール変数を紹介しています。
私のコードは、以下の主な違いを強調し、有益な実装であるかもしれない<クラス=「ポスト・タグ」のhref =「/質問/タグ付き/やる-しばらく」タイトル=「ショーの質問タグ付け 『を実行-しばらく』」 relが= "タグ">行う-ながらのの中をタグ付けtitle="show私はそれを理解する。
だから、この一つのケースでは、あなたは常に少なくとも一度ループを通過します。
first_pass = True
while first_pass or condition:
first_pass = False
do_stuff()
例外は、ループを中断しますので、あなたは同様にループの外でそれを処理することがあります。
try:
while True:
if s:
print s
s = i.next()
except StopIteration:
pass
私はあなたのコードに問題がbreak
内部except
の動作が定義されていないことであると思います。一般break
ので、例えば、一つだけのレベル上がりますbreak
内部try
はfinally
のうちではなく、ループの外に(存在する場合)try
に直接行きます。
関連PEP: http://www.python.org/dev/peps/pep -3136 の
関連質問:ネストされたループする
do {
stuff()
} while (condition())
- >
while True:
stuff()
if not condition():
break
あなたが機能を行うことができます:
def do_while(stuff, condition):
while condition(stuff()):
pass
しかし、 1)それは醜いです。 2)条件は、(それがループしながら、古典を使用するには、のないの唯一の理由です。)のもので満たされることになって一つのパラメータを持つ関数、でなければなりません。
ここでは異なるパターンのスゴ溶液です。コードはまだ非常に似ているが、一つの重要な違いを持ちます。全くの終了条件はありません!あなたは、データとそれを給餌停止したときにコルーチン(本当にコルーチンの連鎖は)ちょうど停止します。
def coroutine(func):
"""Coroutine decorator
Coroutines must be started, advanced to their first "yield" point,
and this decorator does this automatically.
"""
def startcr(*ar, **kw):
cr = func(*ar, **kw)
cr.next()
return cr
return startcr
@coroutine
def collector(storage):
"""Act as "sink" and collect all sent in @storage"""
while True:
storage.append((yield))
@coroutine
def state_machine(sink):
""" .send() new parts to be tokenized by the state machine,
tokens are passed on to @sink
"""
s = ""
state = STATE_CODE
while True:
if state is STATE_CODE :
if "//" in s :
sink.send((TOKEN_COMMENT, s.split( "//" )[1] ))
state = STATE_COMMENT
else :
sink.send(( TOKEN_CODE, s ))
if state is STATE_COMMENT :
if "//" in s :
sink.send(( TOKEN_COMMENT, s.split( "//" )[1] ))
else
state = STATE_CODE
# re-evaluate same line
continue
s = (yield)
tokens = []
sm = state_machine(collector(tokens))
for piece in i:
sm.send(piece)
上記のコードはtokens
にタプルとしてすべてのトークンを収集し、私は、元のコードで.append()
と.add()
差がないと仮定します。
次のように私はこれをやった方法です...
condition = True
while condition:
do_stuff()
condition = (<something that evaluates to True or False>)
これは、私はすでにここでそれを見ていない驚いている、単純な解決策になると私には思えます。これは明らかにも、
に反転することができますwhile not condition:
など。
DO用 - ループはトライ文を含むながら、
loop = True
while loop:
generic_stuff()
try:
questionable_stuff()
# to break from successful completion
# loop = False
except:
optional_stuff()
# to break from unsuccessful completion -
# the case referenced in the OP's question
loop = False
finally:
more_generic_stuff()
その代わりに、「最終的には」節のための必要はありませんとき
while True:
generic_stuff()
try:
questionable_stuff()
# to break from successful completion
# break
except:
optional_stuff()
# to break from unsuccessful completion -
# the case referenced in the OP's question
break
while condition is True:
stuff()
else:
stuff()
クイックハックます:
def dowhile(func = None, condition = None):
if not func or not condition:
return
else:
func()
while condition():
func()
そのように使用します:
>>> x = 10
>>> def f():
... global x
... x = x - 1
>>> def c():
global x
return x > 0
>>> dowhile(f, c)
>>> print x
0
なぜあなたはちょうどいたしません。
for s in l :
print s
print "done"
を参照してください:
例外ハンドラ内でフラグを設定し、sの上で作業する前にそれを確認します。
flagBreak = false;
while True :
if flagBreak : break
if s :
print s
try :
s = i.next()
except StopIteration :
flagBreak = true
print "done"
リソースがunavaliableまたは例外をスロー何か似ている間、あなたがループしているシナリオであれば、あなたは
のようなものを使用することができますimport time
while True:
try:
f = open('some/path', 'r')
except IOError:
print('File could not be read. Retrying in 5 seconds')
time.sleep(5)
else:
break