Дивна поведінка Try-Except-Else-нарешті з операторами Return


88

Це якийсь код, який поводиться своєрідно. Це спрощена версія поведінки, яку я написав. Це все одно продемонструє дивну поведінку, і я мав кілька конкретних запитань щодо того, чому це відбувається.

Я використовую Python 2.6.6 у Windows 7.

def demo1():
    try:
        raise RuntimeError,"To Force Issue"
    except:
        return 1
    else:
        return 2
    finally:
        return 3

def demo2():
    try:
        try:
            raise RuntimeError,"To Force Issue"
        except:
            return 1
        else:
            return 2
        finally:
            return 3
    except:
        print 4
    else:
        print 5
    finally:
        print 6

Результати:

>>> print demo1()
3
>>> print demo2()
6
3
  • Чому демо-версія повертає 3 замість 1?
  • Чому демонстраційно два друкуються 6, а не 6 з / 4 або 5?

Відповіді:


124

Оскільки finallyоператори гарантовано виконуються (ну, припускаючи відсутність відключення електроенергії або щось поза межами контролю Python). Це означає, що перш ніж функція зможе повернутися, вона повинна запустити блок нарешті, який повертає інше значення.

Документи Python :

Коли оператор return, break або continue виконується в наборі try оператора try… final, то також виконується пропозиція „на виході”.

Повернене значення функції визначається останнім виконаним оператором return. Оскільки пропозиція END завжди виконується, оператор return, який виконується в реченні END, завжди буде останнім:

Це означає, що при спробі повернення finallyвикликається блок, який повертає його значення, а не те, яке ви мали б.


4
чому не друкується 5 у другому прикладі? це все ще погано пояснено, я думаю. на повернення добре відповіли, але чому не друкує 5 у другому прикладі
Джоран Бізлі

5
о, я думаю, я це зрозумів, повернення в початковій спробі змушує його негайно перейти до зовнішнього, нарешті
Джоран Бізлі

2
Саме тому, що finallyблоки завжди працюють.
Gareth Latty

2
Чому в демо-версії два він виконує вкладене нарешті, виштовхує назовні, нарешті, а потім повертається у вкладене нарешті, щоб закінчити повернення, а не просто повертає None ззовні остаточно?
Кайл Оуенс,

1
Оскільки при returnвиклику оператора Python перевіряє наявність будь-яких відкритих finallyречень, які потрібно виконати (див. Цитату вище).
Gareth Latty

6

Порядок виконання:

  1. спробуйте заблокувати все нормально -> нарешті заблокувати -> функція закінчується
  2. спробуйте запустити блок і потрапити у виняток A -> нарешті block -> функція закінчується
  3. try block зробить значення, яке повертається, і виклик return -> нарешті блок -> спливаюче значення повернення -> функція закінчується

Отже, будь-яке повернення в блоці нарешті завершить кроки заздалегідь.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.