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é else
se usa aquí como palabra clave, ya que sugiere que el código en cuestión solo se ejecuta si el for
bloque 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 for
declaración hasta el else
bloqueo. Para mí, continue
o continuewith
tendrí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
break
se usa mucho en los bucles "Lo he encontrado" , puede traducirlo a "si no lo encuentra" , que no está lejos de lo que seelse
leefor ... 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
for
ejemplos 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
/except
y no usar ningún valor predeterminado en lugar de unif
/else
.for/else
construcción.else
se emparejó con unfor
y no tenía idea de que era legal.break
instrucción se ejecute explícitamente como en este ejemplo. De los documentos anteriores: "Laelse
cláusula tiene otro problema percibido: si no hay ningunabreak
en el bucle, laelse
clá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
...else
construye que tienesCompare esto con un método que no utiliza este azúcar sintáctico:
En el primer caso, el
raise
está 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 parts
libro.process(i)
sucede para cada artículomylist
estrictamente antestheflag
y no paratheflag
sí mismo? ¿Es lo que se pretendía?process
se ejecutará en cada unoi
que exista en la lista antes de quetheflag
se alcance, no se ejecutará en elementos de la lista despuéstheflag
y 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 ... else
construcció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 ... else
constructo fue ideado por Donald Knuth como un reemplazo para ciertosGOTO
casos de uso;else
palabra clave tenía sentido porque "es lo que Knuth usó, y la gente sabía, en ese momento, que todas [lasfor
declaraciones] habían incrustadoif
yGOTO
debajo, 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é
else
se reutilizó en primer lugar, bueno, aparentemente parecía una buena idea en ese momento.Personalmente, me gusta el compromiso de comentar
# no break
en línea donde seaelse
que 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
finally
que 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?finally
no 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).finally
porque la cláusula else se ejecuta también cuandocontinue
se usa en el bucle for, eso es posiblemente muchas veces y no solo al final.else
ejecución de la cláusula @pepr no se ve afectada porcontinue
( documentos y código de prueba )else
se ejecuta solo cuandocontinue
fue el de la última iteración.Para hacerlo simple, puedes pensarlo así;
break
comando en elfor
bucle,else
no se llamará a la parte.break
comando en elfor
bucle,else
se llamará a la parte.En otras palabras, si la iteración for loop no se "rompe" con
break
, laelse
parte se llamará.fuente
else
bloque 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 paraelse
ser 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
else
palabra 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
while
yfor
declaraciones crea confusión. La razón, nuestra carrera como programadores nos ha enseñado que laelse
declaració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 / else
indicar un camino a seguir . Los bucles siguen un camino hasta que se completa el "objetivo" .El problema es que
else
es 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
iterable
se 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
else
in , todas las cuales son equivalentes, son:For... else
While... else
else
==
if the loop completes normally (without a break or error)
else
==
if the loop does not encounter a break
else
==
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
else
tiene sentido sin el 'descanso', por lo quefor...else
incluye:Entonces, los elementos esenciales de un
for...else
bucle 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
else
palabra clave puede ser confuso aquí, y como muchas personas tienen puntas hacia fuera, algo asínobreak
,notbreak
es 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
break
en un tipo especial deException
:La diferencia es
python
implicaexcept break
y 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
else
bloque de instrucciones se ejecutarán cuando elfor
ciclo 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
break
al final de suif
bloque. La implicación opuesta, esewhile
ciclo es una extensiónif
, es más común (es solo una verificación condicional repetida / en bucle), porque aif
menudo se enseña anteswhile
. Sin embargo, eso no es cierto porque eso significaríaelse
bloquear 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,
else
como 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 clause
se completa"Está manejando escribir declaraciones tan largas como "se completa la cláusula for", por lo que presentan "else"
else
Aquí hay un si en su naturaleza.2, sin embargo, ¿qué tal
for clause is not run at all
Entonces, 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...else
construcción como esta:fuente
Solo estaba tratando de darle sentido nuevamente. ¡Encontré que lo siguiente ayuda!
• Piense en
else
que está emparejado con elif
interior del bucle (en lugar de con elfor
): si se cumple la condición, rompa el bucle, de lo contrario, haga esto, ¡excepto que es unoelse
emparejado con múltiplesif
s!• Si no hay ningún
if
s satisfecho en absoluto, entonces haga loelse
.• ¡Los múltiples
if
s también pueden ser considerados comoif
-elif
s!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