while terminar sintaxis for español ejemplos como ciclo bucle python if-statement for-loop for-else

terminar - for i in range python español



¿Por qué python usa ''else'' después de los bucles for y while? (17)

Aquí hay otro caso de uso idiomático además de buscar. Digamos que quería esperar a que se cumpla una condición, por ejemplo, un puerto que esté abierto en un servidor remoto, junto con algún tiempo de espera. Entonces podrías utilizar un while...else construir así:

import socket import time sock = socket.socket() timeout = time.time() + 15 while time.time() < timeout: if sock.connect_ex((''127.0.0.1'', 80)) is 0: print(''Port is open now!'') break print(''Still waiting...'') else: raise TimeoutError()

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 como la palabra clave aquí, ya que sugiere que el código en cuestión solo se ejecuta si el bloque for no se completa, ¡que es lo opuesto a lo que hace! No importa cómo lo piense, mi cerebro no puede progresar sin problemas desde la instrucción for hasta el bloque else . 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). ¿Tal vez me esté perdiendo algo que haría que tales bloques de código sean más fácilmente descifrables?


Creo que la documentación tiene una gran explicación de otra cosa , continúa

[...] se ejecuta cuando el bucle termina al agotarse la lista (con for) o cuando la condición se vuelve falsa (con while), pero no cuando el bucle termina con una declaración de ruptura ".

Fuente: Documentos de Python 2: Tutorial sobre el flujo de control


Es una construcción extraña incluso para codificadores Python experimentados. Cuando se usa junto con los bucles for, básicamente significa "encontrar algún elemento en el iterable, de lo contrario, si no se encontró ninguno ...". Como en:

found_obj = None for obj in objects: if obj.key == search_key: found_obj = obj break else: print(''No object found.'')

Pero cada vez que vea este constructo, una alternativa mejor es encapsular la búsqueda en una función:

def find_obj(search_key): for obj in objects: if obj.key == search_key: return obj

O use una lista de comprensión:

matching_objs = [o for o in objects if o.key == search_key] if matching_objs: print(''Found {}''.format(matching_objs[0])) else: print(''No object found.'')

No es semánticamente equivalente a las otras dos versiones, pero funciona lo suficientemente bien en el código crítico de no rendimiento donde no importa si se repite la lista completa o no. Otros pueden estar en desacuerdo, pero 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 los hilos de for ... else


Hay una excelente presentación de Raymond Hettinger, titulada Transforming Code into Beautiful, Idiomatic Python , en la que aborda brevemente la historia de la construcción for ... else . La sección relevante es "Distinguir múltiples puntos de salida en bucles" a partir de las 15:50 y continuando durante aproximadamente tres minutos. Aquí están los puntos altos:

  • El constructo for ... else fue ideado por Donald Knuth como un reemplazo para ciertos casos de uso de GOTO ;
  • Reutilizar la palabra clave else tenía sentido porque "es lo que Knuth usaba, y la gente sabía, en ese momento, todos [ for declaraciones] habían incrustado un if y GOTO debajo, y esperaban la else ";
  • En retrospectiva, debería haber sido llamado "no break" (o posiblemente "nobreak"), y entonces no sería confuso. *

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 que el código existente sea práctico. Pero si la pregunta que realmente estás preguntando es por qué else fue reutilizada 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 cualquier else podría confundirse, a simple vista, como pertenecer dentro del bucle. Es razonablemente claro y conciso. Esta opción obtiene una breve mención en el resumen que Bjorn vinculó al final de su respuesta:

Para completar, debo mencionar que con un ligero cambio en la sintaxis, los programadores que desean esta sintaxis pueden tenerla ahora mismo:

for item in sequence: process(item) else: # no break suite

* Cita de bonificación de esa parte del video: "Al igual que si llamáramos a Lambda makefunction, nadie preguntaría: ''¿Qué hace lambda?''"


La forma más fácil que encontré para "obtener" lo que hizo el / el otro lo hizo, y lo que es más importante, cuándo usarlo, fue concentrarse en el lugar en el que salta la declaración de ruptura. La construcción For / else es un solo bloque. La ruptura salta del bloque y, por lo tanto, salta "sobre" la cláusula else. Si el contenido de la cláusula else simplemente siguiera la cláusula for, nunca se saltaría, por lo que habría que proporcionar la lógica equivalente colocándola en un if. Esto se ha dicho antes, pero no exactamente con estas palabras, por lo que puede ayudar a alguien más. Intente ejecutar el siguiente fragmento de código. Estoy incondicionalmente a favor del comentario ''sin interrupción'' para mayor claridad.

for a in range(3): print(a) if a==4: # change value to force break or not break else: #no break +10 for whoever thought of this decoration print(''for completed OK'') print(''statement after for loop'')


La palabra clave else puede ser confusa aquí, y como muchas personas han señalado, algo como nobreak , notbreak es más apropiado.

Para entender for ... else ... lógicamente, compárelo con try...except...else , no if...else... , la mayoría de los programadores de Python están familiarizados con el siguiente código:

try: do_something() except: print("Error happened.") # The try block threw an exception else: print("Everything is find.") # The try block does things just find.

Del mismo modo, piense en la break como un tipo especial de Exception :

for x in iterable: do_something(x) except break: pass # Implied by Python''s loop semantics else: print(''no break encountered'') # No break statement was encountered

La diferencia es que python implica una except break y no se puede escribir, por lo que se convierte en:

for x in iterable: do_something(x) else: print(''no break encountered'') # No break statement was encountered

Sí, sé que esta comparación puede ser difícil y aburrida, pero aclara la confusión.


Lo leí algo así como:

Si aún está en las condiciones para ejecutar el bucle, haga cosas, o haga algo más.


Lo leí como "Cuando el iterable se agote por completo, y la ejecución está a punto de pasar a la siguiente declaración después de terminar el for , se ejecutará la cláusula else". Por lo tanto, cuando la iteración se interrumpe por break , esto no se ejecutará.


Los códigos en el bloque else instrucción se ejecutarán cuando el bucle for no se haya interrumpido.

for x in xrange(1,5): if x == 5: print ''find 5'' break else: print ''can not find 5!'' #can not find 5!

De los docs

Las declaraciones de bucle pueden tener una cláusula más; se ejecuta cuando el bucle termina por agotamiento de la lista (con para) o cuando la condición se vuelve falsa (con while), pero no cuando el bucle termina con una declaración de interrupción. Esto se ejemplifica en el siguiente bucle, que busca números primos:

>>> for n in range(2, 10): ... for x in range(2, n): ... if n % x == 0: ... print(n, ''equals'', x, ''*'', n//x) ... break ... else: ... # loop fell through without finding a factor ... print(n, ''is a prime number'') ... 2 is a prime number 3 is a prime number 4 equals 2 * 2 5 is a prime number 6 equals 2 * 3 7 is a prime number 8 equals 2 * 4 9 equals 3 * 3

(Sí, este es el código correcto. Mire detenidamente: la cláusula else pertenece al bucle for, no a la sentencia if).

Cuando se usa con un bucle, la cláusula else tiene más en común con la cláusula else de una sentencia try que con las sentencias if: la cláusula else de una sentencia try se ejecuta cuando no se produce una excepción, y la cláusula else de un bucle se ejecuta cuando no se produce una ruptura . Para obtener más información sobre la declaración de prueba y las excepciones, consulte Manejo de excepciones.

La instrucción continue, también tomada de C, continúa con la siguiente iteración del bucle:

>>> for num in range(2, 10): ... if num % 2 == 0: ... print("Found an even number", num) ... continue ... print("Found a number", num) Found an even number 2 Found a number 3 Found an even number 4 Found a number 5 Found an even number 6 Found a number 7 Found an even number 8 Found a number 9


Para hacerlo simple, puedes pensar en eso así;

  • Si encuentra el comando break en el bucle for , no se llamará la parte else .
  • Si no encuentra el comando break en el bucle for , se llamará la parte else .

En otras palabras, si para la iteración de bucle no se "rompe" con break , se llamará la parte else .

Es tan simple.


Podrías pensar en ello como, de else forma, en el resto de las cosas, o en otras cosas, que no se hicieron en el bucle.


Porque no querían introducir una nueva palabra clave al lenguaje. Cada uno roba un identificador y causa problemas de compatibilidad hacia atrás, por lo que generalmente es un último recurso.


Supongamos que tenemos una función

def broken(x) : return False if x==5 else True

Lo que significa que solo 5 no está roto. Ahora en caso de quebrado nunca se evalúa con 5: -

for x in range(4): if not broken(x) : break else: print("Everything broken... doom is upon us")

Dará salida: -

Everything broken... doom is upon us

Donde cuando roto se evalúa con 5: -

for x in range(6): if not broken(x) : break else: print("Everything broken... doom is upon us")

No imprimirá nada. Así, indirectamente diciendo que hay al menos algo que no está roto.

Sin embargo, en caso de que quieras hacer trampa y saltarte algo que encontraste fue roto. Es decir, continúe con el bucle aunque haya encontrado 5 como roto, de lo contrario la declaración se imprimirá. Es decir :-

for x in range(6): if not broken(x) : continue else: print("Everything broken... doom is upon us")

Imprimirá

Everything broken... doom is upon us

Espero que despeje la confusión en lugar de crear una nueva :-)


Una construcción común es ejecutar un bucle hasta que se encuentre algo y luego salirse del bucle. El problema es que si salgo del bucle o si el bucle termina, debo determinar qué caso sucedió. Un método es crear una marca o variable de tienda 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 que se encuentre un elemento de marca y luego detener el procesamiento. Si falta el elemento de marca, entonces se debe generar una excepción.

Usando el Python for ... else construye tienes

for i in mylist: if i == theflag: break process(i) else: raise ValueError("List argument missing terminal flag.")

Compare esto con un método que no usa este azúcar sintáctico:

flagfound = False for i in mylist: if i == theflag: flagfound = True break process(i) if not flagfound: raise ValueError("List argument missing terminal flag.")

En el primer caso, el raise está vinculado estrechamente al bucle for con el que funciona. En el segundo, la unión no es tan fuerte y se pueden introducir errores durante el mantenimiento.


Ya que la parte técnica ha sido bastante respondida, mi comentario está relacionado con la confusión que produce esta palabra clave reciclada .

Al ser Python, un lenguaje de programación muy elocuente , el mal uso de una palabra clave es más notorio. La palabra clave else describe perfectamente parte del flujo de un árbol de decisión, "si no puede hacer esto, (else) haga eso". Está implícito en nuestro propio idioma.

En su lugar, el uso de esta palabra clave con while y for declaraciones crea confusión. La razón, nuestra carrera como programadores nos ha enseñado que la declaración else reside dentro de un árbol de decisión; su alcance lógico , un contenedor que condicionalmente devuelve una ruta a seguir. Mientras tanto, las declaraciones de bucle tienen un objetivo explícito figurativo para alcanzar algo. El objetivo se cumple después de continuas iteraciones de un proceso.

if / else indica 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. Python y Human Language comparten la semántica de la palabra. Pero la palabra else en Human Language nunca se usa para indicar las acciones que alguien o algo tomará después de que se complete algo. Se utilizará si, en el proceso de completarlo, surge un problema (más como una declaración de ruptura ).

Al final, la palabra clave permanecerá en Python. Está claro que fue un error, más claro cuando cada programador intenta crear una historia para entender su uso como un dispositivo mnemotécnico. Me hubiera encantado si hubieran elegido la palabra clave. Creo que esta palabra clave encaja perfectamente en ese flujo iterativo, la recompensa después del bucle.

Se parece a la situación que tiene un niño después de seguir cada paso para armar un juguete: ¿Y ENTONCES, qué papá?


Estoy de acuerdo, es más como un ''Elif no [condición (s) que levanta la ruptura]''.

Sé que este es un hilo antiguo, pero estoy analizando la misma pregunta en este momento, y no estoy seguro de que alguien haya captado la respuesta a esta pregunta de la forma en que la entiendo.

Para mí, hay tres formas de "leer" el else en For... else o While... else , todas las cuales son equivalentes, son:

  1. else == if the loop completes normally (without a break or error)
  2. else == if the loop does not encounter a break
  3. else == else not (condition raising break) (presumiblemente existe tal condición, o usted no tendría un bucle)

Entonces, esencialmente, el "else" en un bucle es realmente un "elif ..." donde ''...'' es (1) sin interrupción, lo que es equivalente a (2) NOT [condición (s) levantando ruptura].

Creo que la clave es que la else tiene sentido sin el ''descanso'', por lo que un for...else incluye:

for: do stuff conditional break # implied by else else not break: do more stuff

Por lo tanto, los elementos esenciales de un bucle for...else son los siguientes, y los leería en un lenguaje sencillo como:

for: do stuff condition: break else: # read as "else not break" or "else not condition" do more stuff

Como han dicho los otros carteles, generalmente se genera una ruptura cuando puede localizar lo que su bucle está buscando, por lo que la else: convierte en "qué hacer si el elemento de destino no se encuentra".

Ejemplo

También puede utilizar el manejo de excepciones, los descansos y los bucles todos juntos.

for x in range(0,3): print("x: {}".format(x)) if x == 2: try: raise AssertionError("ASSERTION ERROR: x is {}".format(x)) except: print(AssertionError("ASSERTION ERROR: x is {}".format(x))) break else: print("X loop complete without error")

Resultado

x: 0 x: 1 x: 2 ASSERTION ERROR: x is 2 ---------- # loop not completed (hit break), so else didn''t run

Ejemplo

Ejemplo simple con una ruptura siendo golpeado.

for y in range(0,3): print("y: {}".format(y)) if y == 2: # will be executed print("BREAK: y is {}/n----------".format(y)) break else: # not executed because break is hit print("y_loop completed without break----------/n")

Resultado

y: 0 y: 1 y: 2 BREAK: y is 2 ---------- # loop not completed (hit break), so else didn''t run

Ejemplo

Ejemplo simple donde no hay interrupciones, ninguna condición que genere una interrupción y no se encuentran errores.

for z in range(0,3): print("z: {}".format(z)) if z == 4: # will not be executed print("BREAK: z is {}/n".format(y)) break if z == 4: # will not be executed raise AssertionError("ASSERTION ERROR: x is {}".format(x)) else: print("z_loop complete without break or error/n----------/n")

Resultado

z: 0 z: 1 z: 2 z_loop complete without break or error ----------


for i in range(3): print(i) if i == 2: print("Too big - I''m giving up!") break; else: print("Completed successfully")

"else" aquí es locamente simple, solo significa

1, "si for clause se completa"

for i in range(3): print(i) if i == 2: print("Too big - I''m giving up!") break; if "for clause is completed": print("Completed successfully")

Se está manejando para escribir declaraciones tan largas como "porque la cláusula está completa", por lo que introducen "else".

else aquí hay un si en su naturaleza.

2, sin embargo, ¿qué hay for clause is not run at all

In [331]: for i in range(0): ...: print(i) ...: ...: if i == 9: ...: print("Too big - I''m giving up!") ...: break ...: else: ...: print("Completed successfully") ...: Completed successfully

Así que es completamente enunciado una combinación lógica:

if "for clause is completed" or "not run at all": do else stuff

o ponlo de esta manera:

if "for clause is not partially run": do else stuff

o de esta manera:

if "for clause not encounter a break": do else stuff