[Python, Программирование] Что вернёт эта функции в Python?

Автор Сообщение
news_bot ®

Стаж: 6 лет 3 месяца
Сообщений: 27286

Создавать темы news_bot ® написал(а)
22-Июн-2021 13:42


Всем привет! Сегодня хотел бы обсудить очень простой, но, на мой взгляд, интересный вопрос по Python и его внутреннему устройству. Как вы думаете, что вернёт эта функция:
def foo()
    try:
        return 1
    finally:
        return 2
Если вам интересно, что получится в результате и как это работает, добро пожаловать под кат.Прежде чем давать ответ, давайте разберёмся, что происходит. Для начала рассмотрим самую простую функцию:
def foo():
    return 1
Распечатаем её байт код:
import dis
dis.dis(foo)
Мы увидим следующий вывод:
2         0 LOAD_CONST               1 (1)
            3 RETURN_VALUE
Рассмотрим по шагам:
  • LOAD_CONST загружает константу (в нашем случае 1) и кладет её на вершину стека.
  • RETURN_VALUE возвращает в вызывающий код значение с вершины стека.
Подробнее о байт-коде Python и его командах рассказано тут.Что же скрывается за мифической фразой «возвращает в вызывающий код»? На самом деле, никакой магии не происходит. Если обратиться к исходному коду CPython, то можно увидеть следующие строчки:
switch (opcode) {
    ...
    case RETURN_VALUE: {
        retval = POP();
        why = WHY_RETURN;
        goto fast_block_end;
    }
    ...
}
Как видите, всё очень просто и понятно: мы сохраняем в переменной retval значение с вершины стека и переходим к выходу из текущего блока.Теперь мы готовы посмотреть на байт-код функции из нашего исходного примера. Как же она устроена внутри?
2           0 SETUP_FINALLY            8 (to 11)
  3           3 LOAD_CONST               1 (1)
              6 RETURN_VALUE
              7 POP_BLOCK
              8 LOAD_CONST               0 (None)
  5     >>   11 LOAD_CONST               2 (2)
             14 RETURN_VALUE
             15 END_FINALLY
Опуская излишние подробности, этот код ведёт себя так:
  • Устанавливаем блок try и указываем, где находится finally.
  • Загружаем константу и возвращаем значение.
  • Выполняем некоторые вспомогательные действия.
  • Наконец идёт блок finally (адреса 11, 14, 15), в которым мы снова загружаем константу и делаем ret.
При исполнении кода сначала отрабатывает часть в блоке try, а затем выполняется код из finally. Что же происходит, когда мы снова вызовем RETURN_VALUE? Правильно, мы просто перезапишем возвращаемое значение retval на новое. Ну а функция, разумеется, вернёт 2.Как видите, даже несмотря кажущуюся неочевидность, Python, на мой взгляд, ведёт себя максимально понятно и логично: блок finally выполняется после блока try и его возвращаемое значение «более актуально». Однако, разумеется, на практике писать такой код я крайне не рекомендую ;-)
===========
Источник:
habr.com
===========

Похожие новости: Теги для поиска: #_python, #_programmirovanie (Программирование), #_python, #_try, #_finally, #_return, #_vnutrennee_ustrojstvo (внутреннее устройство), #_interesnoe (интересное), #_osobennosti (особенности), #_blog_kompanii_domklik (
Блог компании ДомКлик
)
, #_python, #_programmirovanie (
Программирование
)
Профиль  ЛС 
Показать сообщения:     

Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы

Текущее время: 20-Май 05:41
Часовой пояс: UTC + 5