python - loop - Rompiendo los bucles anidados
python for loop index (8)
Posible duplicado:
¿Cómo romper con varios bucles en Python?
¿Hay una forma más fácil de romper los bucles anidados que lanzar una excepción? (En Perl, puede asignar etiquetas a cada bucle y al menos continuar con un bucle externo).
for x in range(10):
for y in range(10):
print x*y
if x*y > 50:
"break both loops"
Es decir, hay una manera mejor que:
class BreakIt(Exception): pass
try:
for x in range(10):
for y in range(10):
print x*y
if x*y > 50:
raise BreakIt
except BreakIt:
pass
¡Use itertools.product!
from itertools import product
for x, y in product(range(10), range(10)):
#do whatever you want
break
Aquí hay un enlace a itertools.product en la documentación de python: http://docs.python.org/library/itertools.html#itertools.product
A veces uso una variable booleana. Ingenuo, si lo desea, pero me parece bastante flexible y cómodo para leer. Probar una variable puede evitar volver a probar condiciones complejas y también puede recopilar resultados de varias pruebas en bucles internos.
x_loop_must_break = False
for x in range(10):
for y in range(10):
print x*y
if x*y > 50:
x_loop_must_break = True
break
if x_loop_must_break: break
Al menos ha sido sugerido, pero también rejected . No creo que haya otra forma, excepto repetir la prueba o reorganizar el código. A veces es un poco molesto.
En el mensaje de rechazo , el Sr. van Rossum menciona el uso de return
, que es realmente sensato y algo que debo recordar personalmente. :)
En este caso particular, puede combinar los bucles con un python moderno (3.0 y probablemente 2.6, también) mediante el uso de itertools.product.
Por mi parte, tomé esto como una regla general, si anida demasiados bucles (como en más de 2), generalmente puede extraer uno de los bucles en un método diferente o fusionar los bucles en uno, como en este caso.
Si puede extraer el código de bucle en una función, se puede usar una declaración de return
para salir del bucle más externo en cualquier momento.
def foo():
for x in range(10):
for y in range(10):
print x*y
if x*y > 50:
return
foo()
Si es difícil extraer esa función, podría usar una función interna, como sugiere @ bjd2385, por ejemplo
def your_outer_func():
...
def inner_func():
for x in range(10):
for y in range(10):
print x*y
if x*y > 50:
return
inner_func()
...
Si va a generar una excepción, puede generar una excepción StopIteration . Eso al menos hará evidente la intención.
También puede refactorizar su código para usar un generador. Pero esto puede no ser una solución para todos los tipos de bucles anidados.
for x in xrange(10):
for y in xrange(10):
print x*y
if x*y > 50:
break
else:
continue # only executed if the inner loop did NOT break
break # only executed if the inner loop DID break
Lo mismo funciona para bucles más profundos:
for x in xrange(10):
for y in xrange(10):
for z in xrange(10):
print x,y,z
if x*y*z == 30:
break
else:
continue
break
else:
continue
break