Python, the stack, and the heap

eryk sun eryksun at gmail.com
Mon Dec 17 17:10:45 EST 2018


On 12/17/18, Rob Gaddi <rgaddi at highlandtechnology.invalid> wrote:
>
> Python's objects all have a lifespan dictated by the continued existence
> of references to them and thus can transcend the lifetime of the current
> function in ways not known at translation time.  So am I right in
> thinking that all Python objects are out on the heap?  And that the
> references themselves may or may not wind up on the stack depending on
> what flavor you're running?

Objects are heap allocated and use reference counting in CPython (i.e.
Python implemented in C). A scope reference in CPython could be a fast
(function) local that's internal to a frame object; a cell object
that's used to share variables in nested scopes; a locals dict item in
an unoptimized scope (e.g. module, class, exec); or a temporary
reference in the frame's stack while evaluating bytecode. Commonly the
latter is from a LOAD_* opcode. For example, here's the implementation
of LOAD_FAST:

        TARGET(LOAD_FAST) {
            PyObject *value = GETLOCAL(oparg);
            if (value == NULL) {
                format_exc_check_arg(PyExc_UnboundLocalError,
                                     UNBOUNDLOCAL_ERROR_MSG,
                                     PyTuple_GetItem(co->co_varnames, oparg));
                goto error;

            Py_INCREF(value);
            PUSH(value);
            FAST_DISPATCH();
        }

The above gets the object pointer from the frame's fastlocals array,
increments the object's reference count, and pushes the pointer on the
frame's stack.

Note that the bytecode evaluation stack is part of the heap-allocated
frame object. It's not the native thread stack (sometimes called the C
stack when code is written in C), but there's a rough correspondence
between frame objects and the native stack, since the interpreter
calls a C function to evaluate a Python frame.


More information about the Python-list mailing list