Что это означает, что Python основан на стеке?
Я прочитал, как CPython основан на стеке. Что это значит? Когда я использую модуль dis, я вижу такие операции, как LOAD_FAST и т. Д., Где значения помещаются в стек. Но я прочитал, что все значения в Python являются объектами и, следовательно, идут в кучу. Я думаю, что я путаю две разные вещи здесь. Я также читал, что есть нечто, называемое Python без стека. Может кто-то уточнить это?
2 ответа
Самый популярный интерпретатор Python, CPython, можно рассматривать как виртуальную машину, основанную на стеке. Это означает, что код Python скомпилирован для воображаемого (виртуального) компьютера с архитектурой стека.
Другой аспект заключается в том, как реализована эта виртуальная машина. Это явно не аппаратное обеспечение (и попытки производителей процессоров добавить поддержку некоторых виртуальных машин, например JVM, обычно не приносят успеха). Таким образом, этот стековый компьютер эмулируется программой, написанной на C, и является частью интерпретатора CPython.
Относительно того, как стек и куча живут вместе, теперь должно быть понятно - и виртуальная машина, и стек размещены в памяти кучи. С помощью LOAD_FAST
помещает объект на вершину стека с точки зрения виртуальной машины, и та же самая инструкция помещает объект в кучу с точки зрения ОС.
Все не черно-белое. Значение на основе стека не должно восприниматься как исключение возможности сохранения данных в куче.
Прежде всего, это только ссылки на объекты, которые живут в стеке в виртуальной машине, но все же не все ссылки живут там (есть ссылки на другие объекты в объектах, которые также живут в куче).
Стек здесь состоит в том, что временные данные хранятся в стеке, а не в регистрах. Это означает, что если вы хотите добавить два числа, вы помещаете их в стек, а затем выполняете инструкцию сложения в отличие от регистрационной машины, вы помещаете их в регистры и складываете их вместе.
Теперь, поскольку время жизни объектов не ограничено таким образом, что позволяет (или, по крайней мере, возможно) размещать их в стеке, вы должны дополнить эту модель кучей для хранения реальных объектов.
Кроме того, довольно непрактично быть рабом модели стека. Например, виртуальная машина должна иметь доступ к глобальной области (которая по определению является dict
-подобный объект). Хотя это можно решить, всегда имея в стеке ссылку на глобальную область видимости, это довольно непрактично. Вместо этого есть инструкции для прямого поиска в глобальной области видимости. Аналогичные рассуждения применимы к локальной области видимости: все локальные переменные могут лежать в стеке, но вместо этого они хранятся в массиве, который больше похож на тот, который будет иметь место на машине регистрации, вот где LOAD_FAST
входит в картину.
Таким образом, факт заключается в том, что виртуальная машина CPython представляет собой смесь компьютера регистра и стека.
Что касается Python без стека, это также несколько сбивает с толку. Стек с таким именем не относится к одному и тому же стеку. Вместо этого он ссылается на C-стек, и это не означает, что он свободен от C-стека, но скорее интерпретатор Python не использует стек вызовов C для отслеживания стека вызовов Python. На самом деле это означает, что Python без стека имеет больше стека в виртуальной машине, чем CPython, а не меньше.
Разница в том, что происходит, когда вы вызываете функцию. В CPython виртуальная машина просто вызывает себя для выполнения метода, который будет означать, что информация о том, как вернуться к вызывающей стороне, сохраняется в стеке C. С другой стороны, в Python без стека обратный адрес помещается в стек Python, и виртуальная машина продолжает выполнять функцию напрямую, а информация о том, как вернуться к вызывающей стороне, сохраняется в стеке VM. Одно преимущество Python без стека состоит в том, что каждый поток Python не должен выполняться с отдельным потоком в C (это означает, что Python без стека может иметь поток даже на платформах, которые не поддерживают многопоточность).
Существуют реализации Python, которые вместо этого используют машину регистрации, но с другой стороны, она тоже не черно-белая. Как вы, вероятно, поняли, что для вызова функции потребуется где-то хранить возвращаемую информацию, и в основном требуется, чтобы она хранилась в стеке. Так что это тоже смесь стековой машины и регистрационной машины. Конечно, он мог бы использовать стек C для сохранения информации для возврата вызывающей стороне, что может сделать стек недоступным для ВМ.