try / else z return w bloku try

Natknąłem się na dziwne zachowanie w Pythonie. Nie mogłem znaleźć informacji na ten temat w pomocy Pythona lub na SE, więc tutaj jest:

def divide(x, y):
    print 'entering divide'
    try:
        return x/y
    except:
        print 'error'
    else:
        print 'no error'
    finally:
        print 'exit'

print divide(1, 1)
print divide(1, 0)

Wyjście:

entering divide
exit
1
entering divide
error
exit
None

Wygląda na to, że python nie wejdzie do bloku else, jeśli wartość zostanie zwrócona w try. Jednak zawsze będzie w bloku finally. Nie rozumiem dlaczego. Czy ktoś może mi pomóc z tą logiką?

Dzięki

Author: Simon Bergot, 2011-09-16

5 answers

Http://docs.python.org/reference/compound_stmts.html#the-try-statement

Opcjonalna klauzula else jest wykonywana, gdy kontrolka wypływa z koniec klauzuli prób.

Obecnie Kontrola "wypływa z końca", z wyjątkiem przypadku wyjątek lub wykonanie instrukcji return, continue lub break.

 60
Author: wRAR,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-16 08:44:04

Powodem takiego zachowania jest return wewnątrz try.

Gdy wystąpi wyjątek, zarówno finally, jak i except bloki wykonują się przed return. W przeciwnym przypadku, gdy nie występuje wyjątek, else działa, a except Nie.

To działa zgodnie z oczekiwaniami:

def divide(x, y):
    print 'entering divide'
    result = 0
    try:
        result = x/y
    except:
        print 'error'
    else:
        print 'no error'
    finally:
        print 'exit'

    return result

print divide(1, 1)
print divide(1, 0)
 17
Author: Saul,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-24 23:14:19

Blok else nie jest wykonywany, ponieważ opuściłeś funkcję, zanim zdążyła to zrobić.

Blok finally jest jednak zawsze wykonywany (chyba, że wyciągniesz kabel zasilający lub coś w tym stylu).

Rozważ to (jako eksperyment myślowy; proszę nie rób tego w prawdziwym kodzie):

def whoops():
    try:
        return True
    finally:
        return False

Zobacz co zwraca:

>>> whoops()
False

Jeśli uznasz to za mylące, nie jesteś sam. Niektóre języki, takie jak C#, aktywnie uniemożliwiają umieszczanie return W finally klauzula.

 15
Author: Tim Pietzcker,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-16 08:51:03

Dlaczego klauzula else nie działa?

Klauzula else jest przydatna dla kodu, który musi zostać wykonany , jeśli klauzula try nie wywołuje wyjątku.

  • Kiedy wywołujesz divide(1, 0), twoja try klauzula wywołuje wyjątek ZeroDivisionError, tak więc klauzula else nie działa.

  • Po wywołaniu divide(1, 1), klauzula try działa pomyślnie, i zwraca . Więc klauzula else nigdy nie jest / align = "left" /


Dlaczego klauzula finally zawsze działa?

Klauzula finallyjest zawsze wykonywana przed opuszczeniem instrukcji try, niezależnie od tego, czy wystąpił wyjątek, czy nie.

Patrz wyżej.


Odniesienie https://docs.python.org/3.5/tutorial/errors.html

 5
Author: kgf3JfUtW,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-13 21:01:32

"return" kończy funkcję i zwraca to, co chcesz, aby zwracała. Więc to nie będzie trwało oczywiście. "wreszcie" jest zawsze wykonywane.

 1
Author: Musaab,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-16 08:48:41