while switch infinito hacer for ejercicios ejemplos ejemplo condiciones con como bucle anidado python while-loop do-while

switch - while anidado python



¿Emular un bucle do-while en Python? (13)

Necesito emular un bucle do-while en un programa de Python. Desafortunadamente, el siguiente código simple no funciona:

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

En lugar de "1,2,3, hecho", imprime el siguiente resultado:

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

¿Qué puedo hacer para detectar la excepción ''parar iteración'' y romper un bucle de tiempo correctamente?

Un ejemplo de por qué tal cosa puede ser necesaria se muestra a continuación como pseudocódigo.

Máquina estatal:

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


A ver si esto ayuda:

Coloque una bandera dentro del controlador de excepciones y verifíquela antes de trabajar en el s.

flagBreak = false; while True : if flagBreak : break if s : print s try : s = i.next() except StopIteration : flagBreak = true print "done"


Aquí hay una manera muy simple de emular un bucle do-while:

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

Las características clave de un bucle do-while son que el cuerpo del bucle siempre se ejecuta al menos una vez, y que la condición se evalúa en la parte inferior del cuerpo del bucle. La estructura de control que se muestra aquí cumple ambos objetivos sin necesidad de excepciones ni declaraciones de interrupción. Se introduce una variable booleana extra.


Aquí hay una solución más loca de un patrón diferente: usar coroutines. El código sigue siendo muy similar, pero con una diferencia importante; ¡No hay condiciones de salida en absoluto! La coroutine (cadena de coroutines en realidad) simplemente se detiene cuando deja de alimentarla con datos.

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)

El código anterior recopila todos los tokens como tuplas en tokens y asumo que no hay diferencia entre .append() y .add() en el código original.


Corte rápido:

def dowhile(func = None, condition = None): if not func or not condition: return else: func() while condition(): func()

Utilizar como tal:

>>> x = 10 >>> def f(): ... global x ... x = x - 1 >>> def c(): global x return x > 0 >>> dowhile(f, c) >>> print x 0


La excepción romperá el bucle, por lo que también podría manejarlo fuera del bucle.

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

Supongo que el problema con su código es que el comportamiento de break interior, except que no está definido. Por lo general, la break solo sube un nivel, por lo que, por ejemplo, la break interna try ir directamente a finally (si existe) un fuera del try , pero no el bucle.

PEP relacionado: http://www.python.org/dev/peps/pep-3136
Pregunta relacionada: Romper con los bucles anidados.


La forma en que he hecho esto es la siguiente ...

condition = True while condition: do_stuff() condition = (<something that evaluates to True or False>)

Esto me parece la solución simplista, me sorprende que no la haya visto aquí todavía. Esto obviamente también puede ser invertido a

while not condition:

etc.


Mi código a continuación puede ser una implementación útil, destacando la diferencia principal entre do-while y en el while que lo entiendo.

Así que en este caso, siempre pasas por el bucle al menos una vez.

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


No estoy seguro de lo que estás tratando de hacer. Puede implementar un bucle do-while como este:

while True: stuff() if fail_condition: break

O:

stuff() while not fail_condition: stuff()

¿Qué estás haciendo tratando de usar un bucle do while para imprimir las cosas en la lista? ¿Por qué no solo usar:

for i in l: print i print "done"

Actualizar:

Entonces, ¿tienes una lista de líneas? ¿Y quieres seguir iterando a través de él? Qué tal si:

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

¿Eso parece algo cercano a lo que querrías? Con su ejemplo de código, sería:

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


Porque no solo haces

for s in l : print s print "done"

?


Si se encuentra en un escenario en el que está haciendo un bucle mientras un recurso no es valioso o algo similar que lanza una excepción, podría usar algo como

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


para un bucle do - while que contiene declaraciones try

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()

alternativamente, cuando no hay necesidad de la cláusula ''finalmente''

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


do { stuff() } while (condition())

->

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

Puedes hacer una función:

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

Pero 1) es feo. 2) La condición debe ser una función con un parámetro, que se supone que se rellena con cosas (es la única razón para no usar el bucle while clásico).


while condition is True: stuff() else: stuff()