Шаг 183.
Python: тонкости программирования. Питоновские методы повышения производительности. По ту сторону байткода (окончание)

    На этом шаге мы рассмотрим представление кода программы на байткоде.

    Разработчики, работающие над CPython, тоже это поняли. Поэтому они дали нам еще один инструмент, который называется дизассемблером, чтобы сделать инспектирование байтокда легче.

    Дизассемблер байткода Python располагается в модуле dis, который является составной частью стандартной библиотеки. Поэтому мы можем его просто импортировать и вызвать dis.dis() с функцией greet() в качестве аргумента, чтобы получить более удобочитаемое представление о ее байткоде:

>>> import dis
>>> dis.dis(greet)
  2           0 LOAD_CONST               1 ('Привет, ')
              2 LOAD_FAST                0 (name)
              4 BINARY_ADD
              6 LOAD_CONST               2 ('!')
              8 BINARY_ADD
             10 RETURN_VALUE

    Главное, что сделал дизассемблер, было разбиение потока команд и назначение каждому находящемуся в нем коду операции человекочитаемого имени, как, например, LOAD_CONST.

    Вы также видите, как ссылки на константы и переменные теперь чередуются с байткодом и выведены полностью, чтобы уберечь нас от мозговой гимнастики относительно поиска по таблице co_const или co_varnames. Круто!

    Глядя на человекочитаемые коды операций, мы начинаем понимать, как Python представляет и исполняет выражение 'Привет, ' + name + '!' в исходной функции greet().

    Сначала он извлекает константу в индексе 1 ('Привет, ') и помещает ее в стек. Затем он загружает содержимое переменной name и также помещает ее в стек.

    Стек является структурой данных, которая используется в качестве внутренней рабочей памяти виртуальной машины. Существуют разные классы виртуальных машин, и один из них называется стековой машиной. Виртуальная машина Python является реализацией такой стековой машины. Если вся эта штука названа в честь стека, то вы можете себе представить, какую важную роль играет эта структура данных.

    Между прочим, здесь мы касаемся лишь верхов. Если вы интересуетесь этой темой, то дальше найдете рекомендации для дальнейшего изучения. Более глубокое ознакомление с принципами работы виртуальных машин открывает глаза на многое.

    Самое интересное относительно стека как абстрактной структуры данных состоит в том, что на минимальном уровне он поддерживает всего две операции:

Вталкивание добавляет значение на вершину стека, а выталкивание удаляет и возвращает самое верхнее значение. В отличие от массива, в стеке отсутствует способ получить доступ к элементам "ниже" верхнего уровня.

    Давайте предположим, что вначале стек пустой. После того как первые два кода операции были исполнены, содержимое стека виртуальной машины будет выглядеть следующим образом (0 - это самый верхний элемент):

0: 'Гвидо' (содержимое "name")
1: 'Привет, '

    Инструкция BINARY_ADD выталкивает два строковых значения из стека, конкатенирует их, а затем вталкивает результат снова в стек:

0: 'Привет, Гвидо'

    Затем идет еще одна инструкция LOAD_CONST, которая помещает в стек строку с восклицательным знаком:

0: '!'
1: 'Привет, Гвидо'

    Следующий код операции BINARY_ADD снова объединяет два значения, чтобы сгенерировать заключительную приветственную строку:

0: 'Привет, Гвидо!'

    Последняя байткодовая инструкция - RETURN_VALUE, которая сообщает виртуальной машине следующее: то, что в настоящее время находится на вершине стека, является возвращаемым значением этой функции, и поэтому оно может быть передано источнику вызова.

    И - вуаля! - мы только что проследили за тем, как наша функция greet() была исполнена на внутреннем уровне виртуальной машиной Python.

    Можно получить массу удовольствия от создания и определения своих собственных байткодовых языков и построения для них небольших экспериментов с использованием виртуальной машины. По этой теме можно порекомендовать книгу Проектирование компиляторов: виртуальные машины (Compiler Design: Virtual Machines, Wilhelm and Seidl).

    На следующем шаге мы подитожим изученный материал.




Предыдущий шаг Содержание Следующий шаг