1073 Stimmen

Wie emuliert man eine do-while-Schleife?

Ich muss eine do-while-Schleife in einem Python-Programm emulieren. Leider funktioniert der folgende unkomplizierte Code nicht:

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"

Anstelle von "1,2,3,done" wird die folgende Ausgabe gedruckt:

[stdout:]1
[stdout:]2
[stdout:]3
None['Traceback (most recent call last):
', '  File "test_python.py", line 8, in <module>
    s = i.next()
', 'StopIteration
']

Was kann ich tun, um die Ausnahme "Stop Iteration" abzufangen und eine while Schleife richtig zu unterbrechen?

Ein Beispiel dafür, warum so etwas notwendig sein kann, ist unten als Pseudocode dargestellt.

Zustandsmaschine:

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

1283voto

Tom Punkte 20670

Ich bin mir nicht sicher, was Sie zu tun versuchen. Sie können eine do-while-Schleife wie folgt implementieren:

while True:
  stuff()
  if fail_condition:
    break

Oder:

stuff()
while not fail_condition:
  stuff()

Was tun Sie, wenn Sie versuchen, eine do while-Schleife zu verwenden, um das Material in der Liste zu drucken? Warum nicht einfach verwenden:

for i in l:
  print i
print "done"

更新しました。

Haben Sie eine Liste von Zeilen? Und Sie wollen sie immer wieder durchgehen? Wie wäre es mit:

for s in l: 
  while True: 
    stuff() 
    # use a "break" instead of s = i.next()

Kommt das dem nahe, was Sie sich wünschen würden? Mit Ihrem Code-Beispiel wäre es das:

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

390voto

powderflask Punkte 3717

Hier ist eine sehr einfache Möglichkeit, eine do-while-Schleife zu emulieren:

condition = True
while condition:
    # loop body here
    condition = test_loop_condition()
# end of loop

Die wichtigsten Merkmale einer do-while-Schleife sind, dass der Schleifenkörper immer mindestens einmal ausgeführt wird und dass die Bedingung am Ende des Schleifenkörpers ausgewertet wird. Die hier gezeigte Kontrollstruktur erfüllt diese beiden Anforderungen, ohne dass Ausnahmen oder Unterbrechungsanweisungen erforderlich sind. Es wird jedoch eine zusätzliche boolesche Variable eingeführt.

100voto

evan54 Punkte 3219

Mein nachstehender Code könnte eine nützliche Implementierung sein, die den Hauptunterschied zwischen Währenddessenwährend wie ich es verstehe.

In diesem einen Fall durchläuft man die Schleife also immer mindestens einmal.

first_pass = True
while first_pass or condition:
    first_pass = False
    do_stuff()

38voto

ZeD Punkte 541
do {
  stuff()
} while (condition())

->

while True:
  stuff()
  if not condition():
    break

Sie können eine Funktion ausführen:

def do_while(stuff, condition):
  while condition(stuff()):
    pass

Aber 1) Es ist hässlich. 2) Die Bedingung sollte eine Funktion mit einem Parameter sein, der mit etwas gefüllt werden soll (das ist der einzige Grund nicht um die klassische while-Schleife zu verwenden).

35voto

vartec Punkte 124396

Eine Ausnahme unterbricht die Schleife, also können Sie sie auch außerhalb der Schleife behandeln.

try:
  while True:
    if s:
      print s
    s = i.next()
except StopIteration:   
  pass

Ich vermute, dass das Problem mit Ihrem Code darin besteht, dass das Verhalten von break innerhalb except ist nicht definiert. Im Allgemeinen break geht nur eine Ebene höher, also z.B. break innerhalb try geht direkt an finally (falls vorhanden) eine aus dem try aber nicht aus dem Rennen.

Verwandte PEP: http://www.python.org/dev/peps/pep-3136
Verwandte Frage: Ausbrechen aus verschachtelten Schleifen

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X