while terminar for español ejemplos contador como ciclo bucle python break control-flow

terminar - ¿Cómo romper con varios bucles en Python?



for i in range python español (28)

Dado el siguiente código (que no funciona):

while True: #snip: print out current state while True: ok = get_input("Is this ok? (y/n)") if ok == "y" or ok == "Y": break 2 #this doesn''t work :( if ok == "n" or ok == "N": break #do more processing with menus and stuff

¿Hay alguna manera de hacer que esto funcione? ¿O tengo que hacer una comprobación para salir del bucle de entrada, y luego otra, más limitada, verificar el bucle exterior para romper todos juntos si el usuario está satisfecho?

Edit-FYI: get_input es una función corta que escribí que admite la visualización de valores predeterminados y de solicitud y toda esa fantasía y devuelve stdin.readline().strip()


¿Y por qué no seguir buceando si dos condiciones son ciertas? Creo que esta es una forma más pitónica:

dejaVu = True while dejaVu: while True: ok = raw_input("Is this ok? (y/n)") if ok == "y" or ok == "Y" or ok == "n" or ok == "N": dejaVu = False break

¿No es así?

Todo lo mejor.


Aquí hay otro enfoque que es corto. La desventaja es que solo puedes romper el bucle externo, pero a veces es exactamente lo que quieres.

for a in xrange(10): for b in xrange(20): if something(a, b): # Break the inner loop... break else: # Continue if the inner loop wasn''t broken. continue # Inner loop was broken, break the outer. break

(Bystander-EDIT aquí, porque no hemos visto a @yak en mucho tiempo).

Información clave: solo parece que el bucle externo siempre se rompe. Pero si el bucle interno no se rompe, el bucle externo tampoco lo hará.

La declaración continue es la magia aquí. Está en la cláusula for-else. Por definición eso sucede si no hay ruptura interior. En esa situación, elude perfectamente la ruptura exterior.


Dado que esta pregunta se ha convertido en una pregunta estándar para entrar en un bucle particular, me gustaría dar mi respuesta con un ejemplo utilizando Exception .

Si bien no existe una etiqueta con el nombre de ruptura de bucle en una construcción de bucle múltiple, podemos hacer uso de Excepciones definidas por el usuario para dividir en un bucle particular de nuestra elección. Considere el siguiente ejemplo donde imprimimos todos los números de hasta 4 dígitos en el sistema de numeración base-6:

class BreakLoop(Exception): def __init__(self, counter): Exception.__init__(self, ''Exception 1'') self.counter = counter for counter1 in range(6): # Make it 1000 try: thousand = counter1 * 1000 for counter2 in range(6): # Make it 100 try: hundred = counter2 * 100 for counter3 in range(6): # Make it 10 try: ten = counter3 * 10 for counter4 in range(6): try: unit = counter4 value = thousand + hundred + ten + unit if unit == 4 : raise BreakLoop(4) # Don''t break from loop if ten == 30: raise BreakLoop(3) # Break into loop 3 if hundred == 500: raise BreakLoop(2) # Break into loop 2 if thousand == 2000: raise BreakLoop(1) # Break into loop 1 print(''{:04d}''.format(value)) except BreakLoop as bl: if bl.counter != 4: raise bl except BreakLoop as bl: if bl.counter != 3: raise bl except BreakLoop as bl: if bl.counter != 2: raise bl except BreakLoop as bl: pass

Cuando imprimimos la salida, nunca obtendremos ningún valor cuya unidad sea con 4. En ese caso, no salimos de ningún bucle ya que BreakLoop(4) se levanta y se captura en el mismo bucle. De forma similar, cuando diez posiciones tienen 3, entramos en el tercer bucle utilizando BreakLoop(3) . Cada vez que cien lugares tienen 5, entramos en el segundo bucle con BreakLoop(2) y cuando el lugar mil tiene 2, entramos en el primer bucle con BreakLoop(1) .

En resumen, suba su Excepción (incorporada o definida por el usuario) en los bucles internos y cójala en el bucle desde donde desea reanudar su control. Si desea interrumpir todos los bucles, capture la Excepción fuera de todos los bucles. (No he mostrado este caso en el ejemplo).


En este caso, como han señalado otros también, la descomposición funcional es el camino a seguir. Código en Python 3:

def user_confirms(): while True: answer = input("Is this OK? (y/n) ").strip().lower() if answer in "yn": return answer == "y" def main(): while True: # do stuff if user_confirms(): break


Esperemos que esto ayude:

x = True y = True while x == True: while y == True: ok = get_input("Is this ok? (y/n)") if ok == "y" or ok == "Y": x,y = False,False #breaks from both loops if ok == "n" or ok == "N": break #breaks from just one


Esta no es la forma más bonita de hacerlo, pero en mi opinión, es la mejor.

def loop(): while True: #snip: print out current state while True: ok = get_input("Is this ok? (y/n)") if ok == "y" or ok == "Y": return if ok == "n" or ok == "N": break #do more processing with menus and stuff

Estoy bastante seguro de que también podrías resolver algo utilizando la recursión, pero no sé si esa es una buena opción para ti.


Factoriza tu lógica de bucle en un iterador que produce las variables de bucle y regresa cuando está listo. Aquí hay un sencillo que presenta las imágenes en filas / columnas hasta que nos quedamos sin imágenes o lugares para colocarlas:

def it(rows, cols, images): i = 0 for r in xrange(rows): for c in xrange(cols): if i >= len(images): return yield r, c, images[i] i += 1 for r, c, image in it(rows=4, cols=4, images=[''a.jpg'', ''b.jpg'', ''c.jpg'']): ... do something with r, c, image ...

Esto tiene la ventaja de dividir la complicada lógica de bucle y el procesamiento ...


Hay un truco oculto en la estructura de Python while ... else , se puede usar para simular el doble salto sin muchos cambios / adiciones de código. En esencia, si la condición while es falsa, se activa el bloque else . Ninguna de las excepciones, continue o break activan el bloque else . Para obtener más información, consulte las respuestas a la " cláusula Else en Python while statement ", o el documento en Python while (v2.7) .

while True: #snip: print out current state ok = "" while ok != "y" and ok != "n": ok = get_input("Is this ok? (y/n)") if ok == "n" or ok == "N": break # Breaks out of inner loop, skipping else else: break # Breaks out of outer loop #do more processing with menus and stuff

El único inconveniente es que necesita mover la condición de doble ruptura a la condición while (o agregar una variable de marca). También existen variaciones de esto para el bucle for , donde el bloque else se activa después de completar el bucle.


Introduzca una nueva variable que utilizará como un "interruptor de bucle". Primero asigne algo a él (Falso, 0, etc.), y luego, dentro del bucle externo, antes de romper con él, cambie el valor a otra cosa (Verdadero, 1, ...). Una vez que el bucle salga, haga que el bucle ''padre'' verifique ese valor. Déjame demostrar:

breaker = False #our mighty loop exiter! while True: while True: if conditionMet: #insert code here... breaker = True break if breaker: # the interesting part! break # <--- !

Si tienes un bucle infinito, esta es la única salida; para otros loops la ejecución es mucho más rápida. Esto también funciona si tienes muchos bucles anidados. Puedes salir de todo, o solo unos pocos. ¡Posibilidades infinitas! Espero que esto haya ayudado!


La forma en que resuelvo esto es mediante la definición de una variable a la que se hace referencia para determinar si pasas al siguiente nivel o no. En este ejemplo, esta variable se llama ''shouldbreak''.

Variable_That_Counts_To_Three=1 while 1==1: shouldbreak=''no'' Variable_That_Counts_To_Five=0 while 2==2: Variable_That_Counts_To_Five+=1 print(Variable_That_Counts_To_Five) if Variable_That_Counts_To_Five == 5: if Variable_That_Counts_To_Three == 3: shouldbreak=''yes'' break print(''Three Counter = '' + str(Variable_That_Counts_To_Three)) Variable_That_Counts_To_Three+=1 if shouldbreak == ''yes'': break print('''''' This breaks out of two loops!'''''')

Esto le da un gran control sobre cómo exactamente quiere que se rompa el programa, permitiéndole elegir cuándo quiere interrumpir y cuántos niveles bajar.


Me gustaría recordarle que las funciones en Python pueden crearse justo en el medio del código y pueden acceder a las variables circundantes de manera transparente para leer y con global declaración global o nonlocal para escribir.

Por lo tanto, puede usar una función como una "estructura de control rompible", definiendo un lugar al que desea regresar:

def is_prime(number): foo = bar = number def return_here(): nonlocal foo, bar init_bar = bar while foo > 0: bar = init_bar while bar >= foo: if foo*bar == number: return bar -= 1 foo -= 1 return_here() if foo == 1: print(number, ''is prime'') else: print(number, ''='', bar, ''*'', foo)

>>> is_prime(67) 67 is prime >>> is_prime(117) 117 = 13 * 9 >>> is_prime(16) 16 = 4 * 4


Mi primer instinto sería refactorizar el bucle anidado en una función y utilizar el return para romper.


Mi razón para venir aquí es que tenía un bucle externo y uno interno así:

for x in array: for y in dont_use_these_values: if x.value==y: array.remove(x) # fixed, was array.pop(x) in my original answer continue do some other stuff with x

Como puede ver, en realidad no irá a la siguiente x, sino que irá a la siguiente y en su lugar.

Lo que encontré para resolver esto simplemente fue correr a través de la matriz dos veces:

for x in array: for y in dont_use_these_values: if x.value==y: array.remove(x) # fixed, was array.pop(x) in my original answer continue for x in array: do some other stuff with x

Sé que este fue un caso específico de la pregunta de OP, pero lo estoy publicando con la esperanza de que ayude a alguien a pensar sobre su problema de manera diferente mientras mantengo las cosas simples.


Otra forma de reducir su iteración a un bucle de un solo nivel sería mediante el uso de generadores como también se especifica en la referencia de python

for i, j in ((i, j) for i in A for j in B): print(i , j) if (some_condition): break

Podrías escalarlo a cualquier número de niveles para el bucle

El inconveniente es que ya no se puede romper un solo nivel. Es todo o nada.

Otro inconveniente es que no funciona con un bucle while. Originalmente quería publicar esta respuesta en Python - `break ''out of all loops pero desafortunadamente eso está cerrado como un duplicado de este


Para salir de múltiples bucles anidados, sin refactorizar en una función, use una "instrucción de simulación de goto" con la excepción StopIteration incorporada :

try: for outer in range(100): for inner in range(100): if break_early(): raise StopIteration except StopIteration: pass

Vea esta discusión sobre el uso de instrucciones goto para romper los bucles anidados.


Primero, la lógica ordinaria es útil.

Si, por alguna razón, las condiciones de terminación no pueden ser resueltas, las excepciones son un plan alternativo.

class GetOutOfLoop( Exception ): pass try: done= False while not done: isok= False while not (done or isok): ok = get_input("Is this ok? (y/n)") if ok in ("y", "Y") or ok in ("n", "N") : done= True # probably better raise GetOutOfLoop # other stuff except GetOutOfLoop: pass

Para este ejemplo específico, una excepción puede no ser necesaria.

Por otro lado, a menudo tenemos las opciones "Y", "N" y "Q" en las aplicaciones en modo de caracteres. Para la opción "Q", queremos una salida inmediata. Eso es más excepcional.


Primero, también puede considerar hacer que el proceso de obtención y validación de una entrada sea una función; dentro de esa función, solo puede devolver el valor si es correcto, y continuar girando en el bucle while si no. Básicamente, esto evita el problema que resolvió y, por lo general, se puede aplicar en el caso más general (separación de múltiples bucles). Si absolutamente debe mantener esta estructura en su código, y realmente no quiere tratar con los booleanos contables ...

También puede usar goto de la siguiente manera (usando un módulo de April Fools desde here ):

#import the stuff from goto import goto, label while True: #snip: print out current state while True: ok = get_input("Is this ok? (y/n)") if ok == "y" or ok == "Y": goto .breakall if ok == "n" or ok == "N": break #do more processing with menus and stuff label .breakall

Lo sé, lo sé, "no usarás goto" y todo eso, pero funciona bien en casos extraños como este.


Probablemente un pequeño truco como el de abajo lo hará si no prefiere refactorial en función

agregada 1 variable break_level para controlar la condición del bucle while

break_level = 0 # while break_level < 3: # if we have another level of nested loop here while break_level < 2: #snip: print out current state while break_level < 1: ok = get_input("Is this ok? (y/n)") if ok == "y" or ok == "Y": break_level = 2 # break 2 level if ok == "n" or ok == "N": break_level = 1 # break 1 level


Puede definir una variable (por ejemplo, break_statement ), luego cambiarla a un valor diferente cuando ocurra una condición de dos interrupciones y usarla en la instrucción if para separarse también del segundo bucle.

while True: break_statement=0 while True: ok = raw_input("Is this ok? (y/n)") if ok == "n" or ok == "N": break if ok == "y" or ok == "Y": break_statement=1 break if break_statement==1: break


Similar a la anterior, pero más compacta. (Los booleanos son solo números)

breaker = False #our mighty loop exiter! while True: while True: ok = get_input("Is this ok? (y/n)") breaker+= (ok.lower() == "y") break if breaker: # the interesting part! break # <--- !


Tiendo a estar de acuerdo en que refactorizar en una función suele ser el mejor enfoque para este tipo de situación, pero cuando realmente necesita salir de los bucles anidados, aquí hay una interesante variante del enfoque de aumento de excepciones que describió @ S.Lott. Utiliza Python''s with sentencias para hacer que el aumento de excepciones parezca un poco mejor. Defina un nuevo administrador de contexto (solo tiene que hacer esto una vez) con:

from contextlib import contextmanager @contextmanager def nested_break(): class NestedBreakException(Exception): pass try: yield NestedBreakException except NestedBreakException: pass

Ahora puedes usar este administrador de contexto de la siguiente manera:

with nested_break() as mylabel: while True: print "current state" while True: ok = raw_input("Is this ok? (y/n)") if ok == "y" or ok == "Y": raise mylabel if ok == "n" or ok == "N": break print "more processing"

Ventajas: (1) es un poco más limpio (no hay un bloque explícito de prueba de excepción), y (2) obtiene una subclase de Exception para cada uso de nested_break ; no es necesario declarar su propia subclase de Exception cada vez.


Trate de usar un generador infinito.

from itertools import repeat inputs = (get_input("Is this ok? (y/n)") for _ in repeat(None)) response = (i.lower()=="y" for i in inputs if i.lower() in ("y", "n")) while True: #snip: print out current state if next(response): break #do more processing with menus and stuff


Una forma fácil de convertir varios bucles en un solo bucle que se puede numpy.ndindex es usar numpy.ndindex

for i in range(n): for j in range(n): val = x[i, j] break # still inside the outer loop! for i, j in np.ndindex(n, n): val = x[i, j] break # you left the only loop there was!

Tiene que indexar sus objetos, en lugar de poder iterar a través de los valores explícitamente, pero al menos en casos simples parece ser aproximadamente de 2 a 20 veces más simple que la mayoría de las respuestas sugeridas.


PEP 3136 propone rotular rotura / continuar. Guido lo rechazó porque "el código tan complicado para requerir esta característica es muy raro". Sin embargo, el PEP menciona algunas soluciones alternativas (como la técnica de excepción), mientras que Guido siente que refactorizar el uso del retorno será más sencillo en la mayoría de los casos.


Mediante el uso de una función:

def myloop(): for i in range(1,6,1): # 1st loop print(''i:'',i) for j in range(1,11,2): # 2nd loop print('' i, j:'' ,i, j) for k in range(1,21,4): # 3rd loop print('' i,j,k:'', i,j,k) if i%3==0 and j%3==0 and k%3==0: return # getting out of all loops myloop()

Intente ejecutar los códigos anteriores comentando también la return .

Sin utilizar ninguna función:

done = False for i in range(1,6,1): # 1st loop print(''i:'', i) for j in range(1,11,2): # 2nd loop print('' i, j:'' ,i, j) for k in range(1,21,4): # 3rd loop print('' i,j,k:'', i,j,k) if i%3==0 and j%3==0 and k%3==0: done = True break # breaking from 3rd loop if done: break # breaking from 2nd loop if done: break # breaking from 1st loop

Ahora, ejecute los códigos anteriores tal como están primero y luego intente ejecutar comentando cada línea que contiene la break una en una desde la parte inferior.


keeplooping=True while keeplooping: #Do Stuff while keeplooping: #do some other stuff if finisheddoingstuff(): keeplooping=False

o algo así. Podría establecer una variable en el bucle interno y verificarla en el bucle externo inmediatamente después de que el bucle interno salga, rompiendo si corresponde. Me gusta un poco el método GOTO, siempre que no te importe utilizar el módulo de broma de April Fool, no es Pythonic, pero tiene sentido.


break_label = None while True: # snip: print out current state while True: ok = get_input("Is this ok? (y/n)") if ok == "y" or ok == "Y": break_label = "outer" # specify label to break to break if ok == "n" or ok == "N": break if break_label: if break_label != "inner": break # propagate up break_label = None # we have arrived! if break_label: if break_label != "outer": break # propagate up break_label = None # we have arrived! #do more processing with menus and stuff


break_levels = 0 while True: # snip: print out current state while True: ok = get_input("Is this ok? (y/n)") if ok == "y" or ok == "Y": break_levels = 1 # how far nested, excluding this break break if ok == "n" or ok == "N": break # normal break if break_levels: break_levels -= 1 break # pop another level if break_levels: break_levels -= 1 break # ...and so on