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.lower() == "y": break 2 #this doesn't work :(
if ok.lower() == "n": break
#do more processing with menus and stuff
¿Hay alguna manera de hacer que esto funcione? ¿O tengo que hacer una verificación para salir del bucle de entrada, luego otra, más limitada, verificar en el bucle exterior para salir todos juntos si el usuario está satisfecho?
python
nested-loops
break
control-flow
Matthew Scharley
fuente
fuente
goto
si estás enclavado en muchos buclesRespuestas:
Mi primer instinto sería refactorizar el bucle anidado en una función y usar
return
para romper.fuente
return
es el enfoque correcto. Y el razonamiento es que, según el Zen de Python , "plano es mejor que anidado". Tenemos tres niveles de anidamiento aquí y si eso comienza a interferir, es hora de reducir el anidamiento o al menos extraer todo el anidamiento en una función propia.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.
Esto usa la construcción for / else explicada en: ¿Por qué Python usa 'else' después de los bucles for y while?
Visió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
continue
declaración es la magia aquí. Está en la cláusula for-else. Por definición, eso sucede si no hay una ruptura interna. En esa situación,continue
elude cuidadosamente la ruptura exterior.fuente
PEP 3136 propone rotura de descanso / continuar. Guido lo rechazó porque "el código tan complicado que requiere esta función es muy raro". Sin embargo, el PEP menciona algunas soluciones alternativas (como la técnica de excepción), mientras que Guido considera que la refactorización para usar el retorno será más simple en la mayoría de los casos.
fuente
return
es generalmente el camino a seguir, he visto bastantes casos en los que una simplebreak 2
declaración concisa tendría mucho sentido. Además, refactor /return
no funciona de la misma maneracontinue
. En estos casos, la interrupción numérica y la continuación serían más fáciles de seguir y menos complicadas que refactorizar a una función pequeña, generar excepciones o una lógica enrevesada que implica establecer una bandera para que se rompa en cada nivel de nido. Es una pena que Guido lo haya rechazado.break; break
sería bueno.break
todos los bucles. Estúpido.Primero, la lógica ordinaria es útil.
Si, por alguna razón, las condiciones de terminación no se pueden resolver, las excepciones son un plan alternativo.
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.
fuente
done
). (2) planteando una excepción. Fusionarlos en una sola solución solo hace que parezca complicado. Para futuros lectores: CUALQUIERA use todas las líneas que involucrandone
, O definaGetOutOfLoop(Exception)
y aumente / excepto eso.Exception
constructor (por ejemploraise Exception('bla bla bla')
) son válidos tanto en Python 2 como en Python 3. La primera es preferible en este caso porque no queremos nuestroexcept
bloque para capturar todas las excepciones, pero solo la excepción especial que estamos usando para salir del ciclo. Si hacemos las cosas como usted sugiere, y luego un error en nuestro código provoca una excepción inesperada, se tratará erróneamente de la misma manera que se sale deliberadamente del bucle.Tiendo a estar de acuerdo en que la refactorización en una función suele ser el mejor enfoque para este tipo de situación, pero para cuando realmente necesita salir de los bucles anidados, aquí hay una variante interesante del enfoque de aumento de excepciones que describió @ S.Lott. Utiliza la
with
declaración de Python para hacer que el aumento de excepciones se vea un poco mejor. Defina un nuevo administrador de contexto (solo tiene que hacer esto una vez) con:Ahora puede usar este administrador de contexto de la siguiente manera:
Ventajas: (1) es un poco más limpio (sin bloque de prueba explícito), y (2) obtienes una
Exception
subclase personalizada para cada uso denested_break
; No es necesario declarar su propiaException
subclase cada vez.fuente
Primero, también puede considerar hacer que el proceso de obtener y validar la entrada sea una función; dentro de esa función, puede devolver el valor si es correcto y seguir girando mientras tanto bucle si no. Esto esencialmente evita el problema que resolvió y, por lo general, puede aplicarse en el caso más general (ruptura de múltiples bucles). Si absolutamente debe mantener esta estructura en su código, y realmente no quiere tratar con booleanos de contabilidad ...
También puede usar goto de la siguiente manera (usando un módulo de April Fools desde aquí ):
Lo sé, lo sé, "no usarás goto" y todo eso, pero funciona bien en casos extraños como este.
fuente
Introduzca una nueva variable que usará como 'interruptor de bucle'. Primero asigne algo (False, 0, etc.), y luego, dentro del bucle externo, antes de romper, cambie el valor a otra cosa (True, 1, ...). Una vez que el ciclo sale, haga que el ciclo 'padre' verifique ese valor. Déjame demostrarte:
Si tiene un bucle infinito, esta es la única salida; para otros bucles, la ejecución es realmente mucho más rápida. Esto también funciona si tiene muchos bucles anidados. Puede salir de todo, o solo de unos pocos. ¡Posibilidades infinitas! Espero que esto haya ayudado!
fuente
Para salir de múltiples bucles anidados, sin refactorizar en una función, utilice una "instrucción goto simulada" con la excepción StopIteration incorporada :
Vea esta discusión sobre el uso de declaraciones goto para romper bucles anidados.
fuente
o algo así. Puede establecer una variable en el bucle interno y verificarla en el bucle externo inmediatamente después de que el bucle interno salga, rompiéndose si corresponde. Me gusta el método GOTO, siempre que no te importe usar un módulo de bromas de April Fool, no es Pythonic, pero tiene sentido.
fuente
Esta no es la forma más bonita de hacerlo, pero en mi opinión, es la mejor manera.
Estoy bastante seguro de que también podrías resolver algo usando la recursividad, pero no sé si es una buena opción para ti.
fuente
¿Y por qué no seguir haciendo bucles si se cumplen dos condiciones? Creo que esta es una forma más pitónica:
¿No es así?
Todo lo mejor.
fuente
while dejaVu:
? Lo pones en verdad de todos modos.True
condiciones omitir dos bucles, pero solo uno es suficiente.if not dejaVu: break
en la parte inferior y así salir del bucle principal? Creo que la solución está más cerca de lo que se preguntó. +1Factorice su lógica de bucle en un iterador que produzca las variables de bucle y regrese cuando haya terminado: aquí hay una simple que presenta imágenes en filas / columnas hasta que nos quedemos sin imágenes o sin lugares para colocarlas:
Esto tiene la ventaja de dividir la complicada lógica de bucle y el procesamiento ...
fuente
En este caso, como también lo señalaron otros, la descomposición funcional es el camino a seguir. Código en Python 3:
fuente
Hay un truco oculto en la
while ... else
estructura de Python que se puede usar para simular el doble salto sin muchos cambios / adiciones de código. En esencia, si lawhile
condición es falsa,else
se activa el bloque. Ni excepciones,continue
nibreak
activan elelse
bloqueo. Para obtener más información, consulte las respuestas a la " Cláusula Else en Python while ", o Python doc on while (v2.7) .El único inconveniente es que necesita mover la condición de doble ruptura a la
while
condición (o agregar una variable de bandera). Existen variaciones de esto también para elfor
ciclo, donde elelse
bloque se activa después de la finalización del ciclo.fuente
How to break out of multiple loops in Python?
y la respuesta debería haber sido "No funciona, intente otra cosa". Sé que corrige el ejemplo exacto del OP, pero no responde a su pregunta.Otra forma de reducir su iteración a un ciclo de un solo nivel sería mediante el uso de generadores como también se especifica en la referencia de Python
Puede ampliarlo a cualquier número de niveles para el bucle
La desventaja es que ya no puedes romper un solo nivel. Es todo o nada.
Otro inconveniente es que no funciona con un ciclo while. Originalmente quería publicar esta respuesta en Python: `romper` de todos los bucles, pero desafortunadamente eso está cerrado como un duplicado de este
fuente
Mi razón para venir aquí es que tenía un bucle externo y un bucle interno así:
Como puede ver, en realidad no irá a la próxima x, sino a la siguiente y.
Lo que encontré para resolver esto simplemente fue ejecutar la matriz dos veces:
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 en su problema de manera diferente mientras mantiene las cosas simples.
fuente
break
lugar decontinue
haría lo que quieres, ¿no? :-)Intenta usar un generador infinito.
fuente
Al usar una función:
Intente ejecutar los códigos anteriores comentando el
return
.Sin usar ninguna función:
Ahora, ejecute los códigos anteriores tal como están primero y luego intente ejecutar comentando cada línea que contiene
break
una a la vez desde la parte inferior.fuente
Una manera fácil de convertir múltiples bucles en un solo bucle rompible es usar
numpy.ndindex
Debe indexar sus objetos, en lugar de poder recorrer los valores explícitamente, pero al menos en casos simples parece ser aproximadamente 2-20 veces más simple que la mayoría de las respuestas sugeridas.
fuente
fuente
probablemente un pequeño truco como el que se muestra a continuación servirá si no prefiere volver a la función
Se agregó 1 variable break_level para controlar la condición del bucle while
fuente
Puede definir una variable (por ejemplo, break_statement ), luego cambiarla a un valor diferente cuando se produce la condición de dos rupturas y usarla en la instrucción if para romper también desde el segundo bucle.
fuente
Me gustaría recordarle que las funciones en Python se pueden crear justo en el medio del código y pueden acceder a las variables circundantes de forma transparente para leer y con
nonlocal
oglobal
declaración por escrito.Por lo tanto, puede usar una función como una "estructura de control rompible", que define un lugar al que desea regresar:
fuente
Soluciones de 2 maneras
Con un ejemplo: ¿Son estas dos matrices iguales / iguales?
matriz1 y matriz2 son del mismo tamaño, n, 2 matrices dimensionales.
Primera solución , sin función
Segunda solución , con una función
Esta es la solución final para mi caso
¡Que tengas un buen día!
fuente
fuente
Esperemos que esto ayude:
fuente
Aquí hay una implementación que parece funcionar:
El único inconveniente es que debe definir
break_
antes de los bucles.fuente
El crédito es para Vivek Nagarajan, programador desde 1987
Usando la función
Usando bandera
fuente
Similar al anterior, pero más compacto. (Los booleanos son solo números)
fuente
Dado que esta pregunta se ha convertido en una pregunta estándar para entrar en un ciclo particular, me gustaría dar mi respuesta con un ejemplo usando
Exception
.Aunque no existe una etiqueta llamada ruptura del bucle en la construcción de bucle multipally, podemos hacer uso de Excepciones definidas por el usuario para dividirnos en un bucle particular de nuestra elección. Considere el siguiente ejemplo donde imprimamos todos los números de hasta 4 dígitos en el sistema de numeración de base 6:
Cuando imprimimos la salida, nunca obtendremos ningún valor cuyo lugar de unidad sea 4. En ese caso, no saldremos de ningún bucle cuando
BreakLoop(4)
se eleva y se atrapa en el mismo bucle. Del mismo modo, cada vez que diez lugares tienen 3, nos dividimos en el tercer bucle usandoBreakLoop(3)
. Cada vez que cien lugares tienen 5, nosBreakLoop(2)
separamos en el segundo bucle usando y cuando el mil lugar tiene 2, nos separamos en el primer bucle usandoBreakLoop(1)
.En resumen, aumente su Excepción (incorporada o definida por el usuario) en los bucles internos, y recójala en el bucle desde donde desea reanudar su control. Si desea romper todos los bucles, tome la excepción fuera de todos los bucles. (No he mostrado este caso en el ejemplo).
fuente