Programing

파이썬에서 do-while 루프를 에뮬레이트합니까?

crosscheck 2020. 9. 30. 08:41
반응형

파이썬에서 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 vs 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

반응형