1032 votes

-lors de la boucle en Python?

J'ai besoin d'émuler un do-while dans un python. Mais, malheureusement, à la suite de simple code ne fonctionne pas:

l = [ 1, 2, 3 ]
i = l.__iter__()
s = None
while True :
  if s :
    print s
  try :
    s = i.next()
  except StopIteration :
    break
print "done"

Au lieu de "1,2,3,fait" j'ai le résultat suivant:

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

Que puis-je faire pour rattraper "arrêter l'itération' excepton et de briser un certain temps boucle correctement?

Exemple, pourquoi une telle chose peut être nécessaire. L'état de la machine:

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

1250voto

Tom Points 6907

Je ne suis pas sûr de ce que vous essayez de faire. Vous pouvez mettre en œuvre une-lors de la boucle comme ceci:

while True:
  stuff()
  if fail_condition:
    break

Ou:

stuff()
while not fail_condition:
  stuff()

Que faites-vous essayer d'utiliser une boucle do while pour imprimer les trucs dans la liste? Pourquoi ne pas simplement utiliser:

for i in l:
  print i
print "done"

Mise à jour:

Donc, avez-vous une liste de lignes? Et vous voulez garder une itération à travers elle? Comment à ce sujet:

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

Est-ce que semblent comme quelque chose de proche de ce que vous souhaitez? Avec votre code d'exemple, il serait:

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

378voto

powderflask Points 749

Voici un moyen très simple pour émuler une boucle while:

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

Les principales caractéristiques d'un do-while sont que le corps de la boucle s'exécute toujours au moins une fois, et que la condition est évaluée à la fin du corps de la boucle. La structure de contrôle de montrer ici accomplit ces deux n'a besoin d'aucune des exceptions ou break. Elle introduit une variable Booléenne.

38voto

ZeD Points 285
do {
  stuff()
} while (condition())

->

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

Vous pouvez faire une fonction:

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

Mais 1) C'est moche. 2) l'État devrait être une fonction avec un paramètre, censé être rempli par des trucs (c'est la seule raison de ne pas utiliser la classique boucle while.)

35voto

vartec Points 53382

Exception briser la boucle, de sorte que vous pourriez aussi bien le gérer à l'extérieur de la boucle.

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

Je suppose que le problème avec votre code est que le comportement de l' break à l'intérieur d' except n'est pas défini. Généralement, break va à un seul niveau, donc par ex. break à l'intérieur d' try va directement à l' finally (si elle existe) de l' try, mais pas hors de la boucle.

Liés à la PEP: http://www.python.org/dev/peps/pep-3136
Question connexe: http://stackoverflow.com/questions/653509/breaking-out-of-nested-loops

17voto

u0b34a0f6ae Points 14874

Ici, c'est un plus fou de la solution d'un modèle différent -- à l'aide de coroutines. Le code est encore très similaire, mais avec une différence importante: il n'existe pas de conditions de sortie à tous! La coroutine (chaîne de coroutines vraiment) s'arrête juste quand vous arrêter de l'alimenter avec des données.

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)

Le code ci-dessus recueille tous les jetons comme des n-uplets en tokens et je suppose que il n'y a pas de différence entre .append() et .add() dans le code d'origine.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X