2009-10-16 7 views
6

Recientemente he tropezado con una aparente incoherencia en la forma en que Python maneja las cláusulas else en diferentes declaraciones compuestas. Como Python está tan bien diseñado, estoy seguro de que hay una buena explicación, pero no puedo pensar en ello.¿Por qué otra cosa se comporta de manera diferente en las instrucciones for/while en comparación con las declaraciones if/try?

considerar lo siguiente:

if condition: 
    do_something() 
else: 
    do_something_else() 

Aquí, do_something_else() sólo se ejecuta si condition es falso, como se esperaba.

Del mismo modo, en

try: 
    do_something() 
except someException: 
    pass: 
else: 
    do_something_else() 
finally: 
    cleanup() 

do_something_else() sólo se ejecuta si se ha producido no es una excepción.

Pero en los bucles while o while, siempre se ejecuta una cláusula else, independientemente de si el contenido de for/while block se ha ejecutado o no.

for i in some_iterator: 
    print(i) 
else: 
    print("Iterator is empty!") 

siempre imprimirá "iterador está vacía!", Si digo some_iterator = [] o some_iterator = [1,2,3]. Mismo comportamiento en while-else cláusulas. Me parece que else se comporta más como finally en estos casos. ¿Qué estoy pasando por alto?

+0

Me sorprende que Python permita la sintaxis. En la mayoría de los demás idiomas, se limita a usar solo con declaraciones if o switch. Los bucles For y los enunciados try pueden controlar el flujo, pero no son condicionales como un enunciado if, por lo que -else no tiene cabida en ellos. – shuckster

+2

Por lo que vale, ha habido una larga discusión reciente de for/else, et al, en la lista de ideas de python, resumida aquí: http://article.gmane.org/gmane.comp.python.ideas/6131 /. El mismo Guido admite tener dudas al respecto: http://article.gmane.org/gmane.comp.python.ideas/6133/ –

+0

¡Gracias por estos enlaces! –

Respuesta

5

Bueno, depende de cómo lo vea. Usted puede mirar en el que mas te gusta este (con perdón de los gritos, es la única manera de hacer énfasis en el código):

if condition: 
    do_something() 
IF THE PREVIOUS CONDITION WAS FALSE: 
    do_something_else() 

Ahora, hay una similitud evidente entre if/else y try/except/persona, si ves la declaración else como un else a la declaración except. Me gusta esto.

try: 
    do_something() 
IF THERE WAS AN EXCEPTION: 
    pass: 
IF THE PREVIOUS CONDITION WAS FALSE: 
    do_something_else() 
finally: 
    cleanup() 

mismo va para el otro/a:

IF some_iterator IS NOT EMPTY: 
    i = next(some_iterator) 
    print(i) 
IF THE PREVIOUS CONDITION WAS FALSE: 
    print("Iterator is empty!") 

Así que aquí vemos que la cosa de alguna manera fundamental hacer el trabajo exactamente el mismo en los tres casos.

Pero también se puede ver el otro lugar de esta manera:

try: 
    do_something() 
except someException: 
    pass: 
IF NO EXCEPTION: 
    do_something_else() 
finally: 
    cleanup() 

Y entonces no es igual que antes, pero la otra cosa, porque una especie de "si nada más".Se puede ver por/persona de la misma manera:

for i in some_iterator: 
    print(i) 
IF NO MORE ITERATING: 
    print("Iterator is empty!") 

Pero, de nuevo, teniendo en cuenta la elif, a continuación, esta manera de ver funciona para if/else así:

if condition: 
    do_something() 
elif otherconditaion: 
    do_anotherthing() 
IF NO CONDITION WAS TRUE: 
    do_something_else() 

el camino que desea ver el otro depende de usted, pero en ambos sentidos de visualización, de lo contrario, tienen similitudes en los tres casos.

+0

Gracias. Esto tiene sentido y responde mi pregunta. –

13

La construcción for else se ejecuta la cláusula else si se ejecuta ningún break declaración para el bucle, as described here, por ejemplo, esta cláusula lo demás nunca es evaluado

for i in range(1,10): 
    if i % 5 == 0: 
     print i 
     break 
else: 
    print "nothing divisible by 5" 
+0

Correcto, entonces una declaración for/while-else solo tiene sentido si hay una declaración de interrupción en alguna parte. –

4

Sí, como se ha mencionado Eli, la cláusula else sólo se ejecuta si no rompes Se hace que deje de implementación de código como este:

for i in range(1,10): 
    if i % 5 == 0: 
     print i 
     break 
if i % 5 != 0: 
    print "nothing divisible by 5" 

lo que equivale aproximadamente aquí, pero es práctico si las condiciones para dejar de fumar son un poco más complicadas (como la comprobación de diversas condiciones o combinaciones de condiciones posibles).

Cuestiones relacionadas