Entiendo cómo funciona esta construcción:
for i in range(10):
print(i)
if i == 9:
print("Too big - I'm giving up!")
break;
else:
print("Completed successfully")
Pero no entiendo por qué elsese usa aquí como palabra clave, ya que sugiere que el código en cuestión solo se ejecuta si el forbloque no se completa, ¡lo que es lo contrario de lo que hace! No importa cómo lo piense, mi cerebro no puede avanzar sin problemas desde la fordeclaración hasta el elsebloqueo. Para mí, continueo continuewithtendría más sentido (y estoy tratando de entrenarme para leerlo como tal).
Me pregunto cómo los codificadores de Python leen esta construcción en su cabeza (o en voz alta, si lo desea). ¿Quizás me estoy perdiendo algo que haría que tales bloques de código sean más fácilmente descifrables?
python
if-statement
for-loop
for-else
Kent Boogaart
fuente
fuente

breakse usa mucho en los bucles "Lo he encontrado" , puede traducirlo a "si no lo encuentra" , que no está lejos de lo que seelseleefor ... else foo()y simplemente ponerfoo()después del ciclo for?" Y la respuesta es que se comportan de manera diferente solo si el ciclo contiene unbreak(como se describe en detalle a continuación).Respuestas:
Es una construcción extraña incluso para codificadores experimentados de Python. Cuando se usa junto con for-loops, básicamente significa "encontrar algún elemento en el iterable, de lo contrario, si no se encontró ninguno, haga ...". Como en:
Pero cada vez que vea esta construcción, una mejor alternativa es encapsular la búsqueda en una función:
O use una lista de comprensión:
No es semánticamente equivalente a las otras dos versiones, pero funciona lo suficientemente bien en el código crítico que no es de rendimiento donde no importa si itera la lista completa o no. Otros pueden estar en desacuerdo, pero yo personalmente evitaría usar los bloques for-else o while-else en el código de producción.
Ver también [Python-ideas] Resumen de para ... otros hilos
fuente
forejemplos de bucle, y desea usar una expresión de generador / comprensión de lista, entonces quierenext((o for o in objects if o.key == search_key), None)o envolverlo en untry/excepty no usar ningún valor predeterminado en lugar de unif/else.for/elseconstrucción.elsese emparejó con unfory no tenía idea de que era legal.breakinstrucción se ejecute explícitamente como en este ejemplo. De los documentos anteriores: "Laelsecláusula tiene otro problema percibido: si no hay ningunabreaken el bucle, laelsecláusula es funcionalmente redundante". por ejemplofor x in [1, 2, 3]:\n print x\n else:\n print 'this executes due to no break'Una construcción común es ejecutar un bucle hasta que se encuentre algo y luego salir del bucle. El problema es que si salgo del ciclo o el ciclo termina, necesito determinar qué caso sucedió. Un método es crear un indicador o almacenar una variable que me permita hacer una segunda prueba para ver cómo se salió del bucle.
Por ejemplo, suponga que necesito buscar en una lista y procesar cada elemento hasta encontrar un elemento de marca y luego detener el procesamiento. Si falta el elemento de la bandera, se debe generar una excepción.
Usando el Python
for...elseconstruye que tienesCompare esto con un método que no utiliza este azúcar sintáctico:
En el primer caso, el
raiseestá estrechamente unido al bucle for con el que trabaja. En el segundo, el enlace no es tan fuerte y pueden introducirse errores durante el mantenimiento.fuente
Python: the good partslibro.process(i)sucede para cada artículomylistestrictamente antestheflagy no paratheflagsí mismo? ¿Es lo que se pretendía?processse ejecutará en cada unoique exista en la lista antes de quetheflagse alcance, no se ejecutará en elementos de la lista despuéstheflagy no se ejecutará entheflag.Hay una excelente presentación de Raymond Hettinger, titulada Transformando el código en una hermosa pitón idiomática , en la que aborda brevemente la historia de la
for ... elseconstrucción. La sección relevante es "Distinguir múltiples puntos de salida en bucles" a partir de las 15:50 y continuar durante unos tres minutos. Aquí están los puntos altos:for ... elseconstructo fue ideado por Donald Knuth como un reemplazo para ciertosGOTOcasos de uso;elsepalabra clave tenía sentido porque "es lo que Knuth usó, y la gente sabía, en ese momento, que todas [lasfordeclaraciones] habían incrustadoifyGOTOdebajo, y esperaban queelse";Entonces, si la pregunta es, "¿Por qué no cambian esta palabra clave?" entonces Cat Plus Plus probablemente dio la respuesta más precisa : en este punto, sería demasiado destructivo para el código existente para ser práctico. Pero si la pregunta que realmente hace es por qué
elsese reutilizó en primer lugar, bueno, aparentemente parecía una buena idea en ese momento.Personalmente, me gusta el compromiso de comentar
# no breaken línea donde seaelseque pueda confundirse, de un vistazo, como perteneciente al círculo. Es razonablemente claro y conciso. Esta opción recibe una breve mención en el resumen que Bjorn vincula al final de su respuesta:* Cita extra de esa parte del video: "Al igual que si llamamos a la función lambda makefunction, nadie preguntaría, '¿Qué hace lambda?'"
fuente
Porque no querían introducir una nueva palabra clave en el idioma. Cada uno roba un identificador y causa problemas de compatibilidad con versiones anteriores, por lo que generalmente es el último recurso.
fuente
finallyque hubiera sido una mejor opción en ese caso. ¿La palabra clave finalmente aún no estaba presente en el momento en que se introdujo esta construcción?finallyno es mucho mejor, porque implica que el bloque siempre se ejecutará después del ciclo, y no lo es (porque eso sería redundante con solo poner el código para ejecutarlo después del ciclo).finallyporque la cláusula else se ejecuta también cuandocontinuese usa en el bucle for, eso es posiblemente muchas veces y no solo al final.elseejecución de la cláusula @pepr no se ve afectada porcontinue( documentos y código de prueba )elsese ejecuta solo cuandocontinuefue el de la última iteración.Para hacerlo simple, puedes pensarlo así;
breakcomando en elforbucle,elseno se llamará a la parte.breakcomando en elforbucle,elsese llamará a la parte.En otras palabras, si la iteración for loop no se "rompe" con
break, laelseparte se llamará.fuente
elsebloque tampoco se ejecutará si el cuerpo del bucle genera una excepción.La forma más fácil que encontré de 'obtener' lo que hizo el for / else, y lo más importante, cuándo usarlo, fue concentrarme en dónde salta la declaración de ruptura. La construcción For / else es un bloque único. La ruptura salta fuera del bloque, y así salta 'sobre' la cláusula else. Si el contenido de la cláusula else simplemente siguiera a la cláusula for, nunca se saltaría, por lo que la lógica equivalente tendría que proporcionarse poniéndola en un if. Esto se ha dicho antes, pero no del todo en estas palabras, por lo que puede ayudar a alguien más. Intente ejecutar el siguiente fragmento de código. Estoy totalmente a favor del comentario de "no descanso" para mayor claridad.
fuente
for:/else:, realmente no proporciona una justificación para que la palabra clave seaelse. Dado el encuadre dado aquí,then:parece que sería mucho más natural. (No hay razones paraelseser elegido, dados en otras respuestas - que simplemente no están siempre aquí.)Creo que la documentación tiene una gran explicación de lo contrario , continúe
Fuente: Documentos de Python 2: Tutorial sobre flujo de control
fuente
Lo leí algo como:
Si aún está en condiciones de ejecutar el ciclo, haga cosas, de lo contrario , haga otra cosa.
fuente
for:/else:hace que parezcaelse:que siempre se ejecutará después del ciclo, que no es el caso.Dado que la parte técnica ha sido bastante respondida, mi comentario es solo en relación con la confusión que produce esta palabra clave reciclada .
Siendo Python un lenguaje de programación muy elocuente , el mal uso de una palabra clave es más notorio. La
elsepalabra clave describe perfectamente parte del flujo de un árbol de decisión, "si no puede hacer esto, (de lo contrario) haga eso". Está implícito en nuestro propio idioma.En cambio, usar esta palabra clave con
whileyfordeclaraciones crea confusión. La razón, nuestra carrera como programadores nos ha enseñado que laelsedeclaración reside dentro de un árbol de decisión; su alcance lógico , un contenedor que condicionalmente devuelve un camino a seguir. Mientras tanto, las declaraciones de bucle tienen un objetivo figurativo explícito para alcanzar algo. El objetivo se cumple después de iteraciones continuas de un proceso.if / elseindicar un camino a seguir . Los bucles siguen un camino hasta que se completa el "objetivo" .El problema es que
elsees una palabra que define claramente la última opción en una condición. Los semántica de la palabra son ambos compartían por Python y el lenguaje humano. Pero la palabra else en Lenguaje Humano nunca se usa para indicar las acciones que alguien o algo tomarán después de que algo se complete. Se usará si, en el proceso de completarlo, surge un problema (más como una declaración de interrupción ).Al final, la palabra clave permanecerá en Python. Está claro que fue un error, más claro cuando cada programador trata de inventar una historia para comprender su uso como un dispositivo mnemotécnico. Me hubiera encantado si hubieran elegido la palabra clave
then. Creo que esta palabra clave encaja perfectamente en ese flujo iterativo, la recompensa después del ciclo.Se parece a esa situación que tiene un niño después de seguir cada paso en el montaje de un juguete: ¿Y ENTONCES qué papá?
fuente
Lo leí como "Cuando
iterablese agota por completo, y la ejecución está a punto de pasar a la siguiente declaración después de terminarfor, se ejecutará la cláusula else". Por lo tanto, cuando la iteración se rompebreak, esto no se ejecutará.fuente
Estoy de acuerdo, es más como un 'elif no [condición (s) elevando el descanso]'.
Sé que este es un hilo viejo, pero estoy investigando la misma pregunta en este momento, y no estoy seguro de que alguien haya captado la respuesta a esta pregunta en la forma en que la entiendo.
Para mí, hay tres formas de "leer" las declaraciones o
elsein , todas las cuales son equivalentes, son:For... elseWhile... elseelse==if the loop completes normally (without a break or error)else==if the loop does not encounter a breakelse==else not (condition raising break)(presumiblemente existe tal condición, o no tendría un bucle)Entonces, esencialmente, el "else" en un bucle es realmente un "elif ..." donde '...' es (1) sin pausa, que es equivalente a (2) NOT [condición (s) que levanta la pausa].
Creo que la clave es que no
elsetiene sentido sin el 'descanso', por lo quefor...elseincluye:Entonces, los elementos esenciales de un
for...elsebucle son los siguientes, y los leería en inglés simple como:Como han dicho los otros carteles, generalmente se genera un descanso cuando puede localizar lo que está buscando su ciclo, por lo que el
else:convierte en "qué hacer si el elemento objetivo no se encuentra".Ejemplo
También puede usar manejo de excepciones, pausas y bucles todos juntos.
Resultado
Ejemplo
Ejemplo simple con un descanso siendo golpeado.
Resultado
Ejemplo
Ejemplo simple donde no hay interrupción, no hay condición que provoque una interrupción y no se encuentre ningún error.
Resultado
fuente
La
elsepalabra clave puede ser confuso aquí, y como muchas personas tienen puntas hacia fuera, algo asínobreak,notbreakes más apropiado.Para entenderlo
for ... else ...lógicamente, compárelo contry...except...else, noif...else..., la mayoría de los programadores de Python están familiarizados con el siguiente código:Del mismo modo, piense
breaken un tipo especial deException:La diferencia es
pythonimplicaexcept breaky no se puede escribir, por lo que se convierte en:Sí, sé que esta comparación puede ser difícil y agotadora, pero aclara la confusión.
fuente
Los códigos en el
elsebloque de instrucciones se ejecutarán cuando elforciclo no se haya roto.De los documentos: romper y continuar declaraciones, y otras cláusulas en bucles
fuente
Aquí hay una manera de pensar que no he visto a nadie más mencionar arriba:
Primero, recuerde que los bucles for son básicamente azúcar sintáctica alrededor de los bucles while. Por ejemplo, el bucle
puede reescribirse (aproximadamente) como
Segundo, recuerde que los bucles while son básicamente bloques if repetidos. Siempre puede leer un ciclo while como "si esta condición es verdadera, ejecute el cuerpo, luego regrese y verifique nuevamente".
Entonces, while / else tiene mucho sentido: es exactamente la misma estructura que if / else, con la funcionalidad adicional de bucle hasta que la condición se vuelve falsa en lugar de simplemente verificar la condición una vez.
Y luego for / else también tiene perfecto sentido: dado que todos los bucles for son solo azúcar sintáctico encima de los bucles while, solo necesita descubrir cuál es el condicional implícito del bucle while subyacente, y luego lo demás corresponde a cuándo la condición se vuelve falsa.
fuente
Grandes respuestas son:
Mi nota aquí proviene de lo que Donald Knuth dijo una vez (lo siento, no puedo encontrar referencias) de que hay una construcción donde while-else es indistinguible de if-else, es decir (en Python):
tiene el mismo flujo (excluyendo diferencias de bajo nivel) como:
El punto es que if-else puede considerarse como azúcar sintáctico para while-else que está implícito
breakal final de suifbloque. La implicación opuesta, esewhileciclo es una extensiónif, es más común (es solo una verificación condicional repetida / en bucle), porque aifmenudo se enseña anteswhile. Sin embargo, eso no es cierto porque eso significaríaelsebloquear en while-else se ejecutaría cada vez que la condición sea falsa.Para facilitar su comprensión, piense de esa manera:
Otra nota:
fuente
Se podría pensar como,
elsecomo en el resto de las cosas, o las otras cosas, que no se hicieron en el bucle.fuente
"más" aquí es locamente simple, solo significa
1, "si
for clausese completa"Está manejando escribir declaraciones tan largas como "se completa la cláusula for", por lo que presentan "else"
elseAquí hay un si en su naturaleza.2, sin embargo, ¿qué tal
for clause is not run at allEntonces, su declaración es una combinación lógica:
o ponerlo de esta manera:
o de esta manera:
fuente
Aquí hay otro caso de uso idiomático además de la búsqueda. Supongamos que desea esperar a que se cumpla una condición, por ejemplo, que se abra un puerto en un servidor remoto, junto con un tiempo de espera. Entonces podría utilizar una
while...elseconstrucción como esta:fuente
Solo estaba tratando de darle sentido nuevamente. ¡Encontré que lo siguiente ayuda!
• Piense en
elseque está emparejado con elifinterior del bucle (en lugar de con elfor): si se cumple la condición, rompa el bucle, de lo contrario, haga esto, ¡excepto que es unoelseemparejado con múltiplesifs!• Si no hay ningún
ifs satisfecho en absoluto, entonces haga loelse.• ¡Los múltiples
ifs también pueden ser considerados comoif-elifs!fuente
Considero que la estructura que para (si) A bien B, y para (si) -else es un especial if-else , más o menos . Puede ser útil entender más .
A y B se ejecutan como máximo una vez, que es lo mismo que la estructura if-else.
for (if) puede considerarse como un if especial, que realiza un bucle para tratar de cumplir con la condición if. Una vez que se cumple la condición if , A y break ; De lo contrario , B.
fuente
Python usa un bucle else after for y while para que si nada se aplica al loop, algo más suceda. Por ejemplo:
La salida sería 'Hola' una y otra vez (si estoy en lo correcto).
fuente