2009-10-16 14 views
6

Niedawno natknąłem się na pozorną niekonsekwencję w sposobie radzenia sobie z innymi klauzulami Pythona w różnych złożonych stwierdzeniach. Ponieważ Python jest tak dobrze zaprojektowany, jestem pewien, że istnieje dobre wytłumaczenie, ale nie mogę o tym myśleć.Dlaczego zachowuje się inaczej w instrukcjach for/while, a nie w instrukcjach if/try?

Rozważmy następujący:

if condition: 
    do_something() 
else: 
    do_something_else() 

Tutaj do_something_else() jest wykonywana tylko wtedy, gdy condition jest fałszywa, jak oczekiwano.

Podobnie w

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

do_something_else() jest wykonywany tylko wtedy, gdy nie nastąpiło wyłączenie.

Jednak w pętlach for lub while zawsze wykonywana jest klauzula else, niezależnie od tego, czy zawartość for/while block została wykonana, czy nie.

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

zawsze będzie drukować "Iterator jest pusty!", Czy mówię some_iterator = [] lub some_iterator = [1,2,3]. To samo zachowanie w klauzulach while-else. Wydaje mi się, że w takich przypadkach else zachowuje się bardziej jak finally. Co ja przeoczyłem?

+0

Jestem zaskoczony Python pozwala na składnię. W większości innych języków -else jest ograniczone do używania tylko z instrukcjami if lub switch. For-loops i try-instrukcje mogą kontrolować przepływ, ale nie są warunkowe, jak instrukcja if, więc nie ma w nich miejsca. – shuckster

+2

Na ile jest to warte, ostatnio prowadzono dyskusję na temat/else i innych na liście pomysłów Pythona, podsumowanej tutaj: http://article.gmane.org/gmane.comp.python.ideas/6131 /. Sam Guido przyznaje, że o tym myśli: http://article.gmane.org/gmane.comp.python.ideas/6133/ –

+0

Dzięki za te linki! –

Odpowiedz

5

Cóż, to zależy od tego, jak to widzisz. Można spojrzeć na elses tak (przepraszam krzyki, jej jedyny sposób, aby nacisk w kodzie):

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

Teraz istnieje oczywiste podobieństwo pomiędzy if/else i spróbuj/z wyjątkiem/else, jeśli widzisz instrukcję else jako else dla instrukcji except. Lubię to.

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

samo dotyczy innego/za:

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

Tak oto widzimy, że jeszcze w jakiś zasadniczy sposób zrobić działają dokładnie tak samo we wszystkich trzech przypadkach.

Ale można również zobaczyć inny w ten sposób:

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

I to nie jest już takie samo, ale inaczej, bo to swego rodzaju „jeśli nic innego”.Można zobaczyć na/else w ten sam sposób:

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

Ale znowu, biorąc pod uwagę Elif, to sposób widzenia to działa na if/else, a także:

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

, który sposób chcesz spojrzeć na to, co do ciebie należy, ale na oba sposoby patrzenia, w innych przypadkach masz podobieństwa we wszystkich trzech przypadkach.

+0

Dzięki. Ma to sens i odpowiada na moje pytanie. –

13

for else konstrukt wykonuje klauzulę else jeśli nie break wypowiedź została zawarta na pętli as described here Na przykład, klauzula ta jeszcze nigdy nie jest oceniana

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

Prawo, więc instrukcja dla/while-else ma sens tylko wtedy, gdy gdzieś znajduje się instrukcja break. –

4

Tak, jak wspomniano Eli, klauzula else wykonywany jest tylko jeśli się nie złamiesz. Zatrzymuje się od wykonania kodu:

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

co stanowi w przybliżeniu odpowiednik tutaj, ale przydatny, jeśli warunki dla rzucenia palenia są nieco bardziej skomplikowana (jak sprawdzanie różnych możliwych warunki lub kombinacje warunków).

Powiązane problemy