2011-12-07 18 views
12

Recientemente leí this question que tenía una solución sobre etiquetado de bucles en Java.Naming Loops en Python

Me pregunto si existe un sistema de nombres de bucle en Python. He estado varias veces en una situación en la que necesito salir de un círculo externo for desde un lazo interno for. Por lo general, resuelvo este problema colocando el bucle interno en una función que devuelve (entre otros) un booleano que se usa como condición de ruptura. Pero etiquetar los bucles para romperlos parece mucho más simple y me gustaría probar eso, si tal funcionalidad existe en python

¿Alguien sabe si lo hace?

+0

Compruebe la [segunda respuesta] (http://stackoverflow.com/questions/653509/breaking-out-of-nested-loops), hopefull y ayuda a algunos. Pero por lo que puedo ver, no existe ese sistema. –

+0

"¿Pero los bucles de etiquetado para romperse parecen mucho más simples"? Más simple que las funciones adecuadas? ¿Cómo es eso? ¿Puede proporcionar alguna evidencia de cómo esto sería "más simple"? –

+1

No tengo un ejemplo a mano, pero sería una situación en la que tendría que crear una función que se usará solo en ese punto. Quizás "más simple" fue la palabra incorrecta. Lo que quise decir es que no tendría que definir una nueva función solo para usar en ese lugar. – inspectorG4dget

Respuesta

9

Hubo una propuesta para incluir bucles con nombre en python PEP3136, sin embargo, se rechazó con una explicación here. El rechazo se debió principalmente a la rara cantidad de circunstancias donde la legibilidad del código se mejoraría al incluir esta construcción.

1

Nope.

Dependiendo de lo que esté haciendo, es posible que pueda usar algo de itertools para aplanar sus bucles for anidados en un solo bucle for.

8

Aunque hay razones para incluir construcciones con nombre en bucle en el lenguaje, puede evitarlas fácilmente en python sin perder legibilidad. Una implementación del ejemplo se hace referencia en pitón

>>> try: 
    for i in xrange(0,5): 
     for j in xrange(0,6): 
      if i*j > 6: 
       print "Breaking" 
       raise StopIteration 
      print i," ",j 
except StopIteration: 
    print "Done" 


0 0 
0 1 
0 2 
0 3 
0 4 
0 5 
1 0 
1 1 
1 2 
1 3 
1 4 
1 5 
2 0 
2 1 
2 2 
2 3 
Breaking 
Done 
>>> 

I resolver este problema poniendo el bucle interior en una función que retornos (entre otros) un valor booleano que se utiliza como un condición de ruptura.

Creo que deberías probar esto. Esto es muy pitónico, simple y legible.

+2

+1. El uso de excepciones para el control de flujo es perfectamente cromático en Python, aunque se considera un estilo incorrecto en otros idiomas, generalmente por motivos de rendimiento. – kindall

+2

¿Qué sucede si solo quiero "continuar" el ciclo externo, en lugar de detenerlo? – Guillochon

+1

@Guillochon Simplemente ponga la declaración try dentro del primer ciclo – Dylanthepiguy

6

He aquí una manera de salir de múltiples bloques, anidadas utilizando un gestor de contexto:

import contextlib 

@contextlib.contextmanager 
def escapable(): 
    class Escape(RuntimeError): pass 
    class Unblock(object): 
     def escape(self): 
      raise Escape() 

    try: 
     yield Unblock() 
    except Escape: 
     pass 

Usted puede utilizarlo para salir de múltiples bucles:

with escapable() as a: 
    for i in xrange(30): 
     for j in xrange(30): 
      if i * j > 6: 
       a.escape() 

e incluso se puede nido ellos:

with escapable() as a: 
    for i in xrange(30): 
     with escapable() as b: 
      for j in xrange(30): 
       if i * j == 12: 
        b.escape() # Break partway out 
       if i * j == 40: 
        a.escape() # Break all the way out