파이썬에서 do-while 루프를 에뮬레이트합니까?
파이썬 프로그램에서 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, done"대신 다음 출력을 인쇄합니다.
[stdout:]1
[stdout:]2
[stdout:]3
None['Traceback (most recent call last):
', ' File "test_python.py", line 8, in <module>
s = i.next()
', 'StopIteration
']
'반복 중지'예외를 포착하고 while 루프를 올바르게 중단하려면 어떻게해야합니까?
왜 그런 것이 필요한지에 대한 예는 아래에 의사 코드로 표시됩니다.
상태 머신:
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
The key features of a do-while loop are that the loop body always executes at least once, and that the condition is evaluated at the bottom of the loop body. The control structure show here accomplishes both of these with no need for exceptions or break statements. It does introduce one extra Boolean variable.
My code below might be a useful implementation, highlighting the main difference between do-while vs while as I understand it.
So in this one case, you always go through the loop at least once.
first_pass = True
while first_pass or condition:
first_pass = False
do_stuff()
Exception will break the loop, so you might as well handle it outside the loop.
try:
while True:
if s:
print s
s = i.next()
except StopIteration:
pass
I guess that the problem with your code is that behaviour of break
inside except
is not defined. Generally break
goes only one level up, so e.g. break
inside try
goes directly to finally
(if it exists) an out of the try
, but not out of the loop.
Related PEP: http://www.python.org/dev/peps/pep-3136
Related question: Breaking out of nested loops
do {
stuff()
} while (condition())
->
while True:
stuff()
if not condition():
break
You can do a function:
def do_while(stuff, condition):
while condition(stuff()):
pass
But 1) It's ugly. 2) Condition should be a function with one parameter, supposed to be filled by stuff (it's the only reason not to use the classic while loop.)
Here is a crazier solution of a different pattern -- using coroutines. The code is still very similar, but with one important difference; there are no exit conditions at all! The coroutine (chain of coroutines really) just stops when you stop feeding it with data.
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)
The code above collects all tokens as tuples in tokens
and I assume there is no difference between .append()
and .add()
in the original code.
The way I've done this is as follows...
condition = True
while condition:
do_stuff()
condition = (<something that evaluates to True or False>)
This seems to me to be the simplistic solution, I'm surprised I haven't seen it here already. This can obviously also be inverted to
while not condition:
etc.
for a do - while loop containing try statements
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()
alternatively, when there's no need for the 'finally' clause
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()
Quick hack:
def dowhile(func = None, condition = None):
if not func or not condition:
return
else:
func()
while condition():
func()
Use like so:
>>> x = 10
>>> def f():
... global x
... x = x - 1
>>> def c():
global x
return x > 0
>>> dowhile(f, c)
>>> print x
0
Why don't you just do
for s in l :
print s
print "done"
?
See if this helps :
Set a flag inside the exception handler and check it before working on the s.
flagBreak = false;
while True :
if flagBreak : break
if s :
print s
try :
s = i.next()
except StopIteration :
flagBreak = true
print "done"
If you're in a scenario where you are looping while a resource is unavaliable or something similar that throws an exception, you could use something like
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
참고URL : https://stackoverflow.com/questions/743164/emulate-a-do-while-loop-in-python
'Programing' 카테고리의 다른 글
#! (0) | 2020.09.30 |
---|---|
Razor보기 페이지에서 네임 스페이스를 가져 오려면 어떻게하나요? (0) | 2020.09.30 |
Git에서 유효하지 않은 원격 분기 참조를 어떻게 제거합니까? (0) | 2020.09.30 |
JavaScript 배열을 선언 할 때“Array ()”와“[]”의 차이점은 무엇입니까? (0) | 2020.09.29 |
하나의 클라이언트에서 여러 SSH 개인 키를 사용하는 가장 좋은 방법 (0) | 2020.09.29 |