Skip to main content

Include/cpython/listobject.h

Source:

cpython 3.14 @ ab2d84fe1023/Include/cpython/listobject.h

The CPython-internal listobject.h exposes the PyListObject struct layout and fast-path accessor macros. These are used by generated bytecode (via LIST_APPEND and LIST_TO_TUPLE opcodes) and by the C extension API.

Map

LinesSymbolRole
1-15PyListObject structInternal layout: ob_item, allocated
16-36_PyList_ITEMS, PyList_GET_SIZE, PyList_GET_ITEM, PyList_SET_ITEMUnsafe fast accessors

Reading

PyListObject layout

// CPython: Include/cpython/listobject.h:5 PyListObject
typedef struct {
PyObject_VAR_HEAD
/* ob_item is a C array of PyObject* references.
ob_val[ob_size:allocated] are undefined. */
PyObject **ob_item;
Py_ssize_t allocated;
} PyListObject;

ob_size (from PyObject_VAR_HEAD) is the current logical length. allocated is the physical capacity. The list over-allocates using a geometric growth formula to amortize append cost.

Fast accessors

// CPython: Include/cpython/listobject.h:20
#define PyList_GET_ITEM(op, i) (_PyList_ITEMS(op)[i])
#define PyList_SET_ITEM(op, i, v) (_PyList_ITEMS(op)[i] = (v))
#define PyList_GET_SIZE(op) Py_SIZE(op)

PyList_GET_ITEM / PyList_SET_ITEM skip bounds checking and reference counting. They are only safe when the caller is certain the index is valid and manages references manually.

PyList_SET_ITEM does NOT decrement the old item's refcount. It is only safe for freshly allocated list slots where ob_item[i] is uninitialized (NULL or garbage).

PyList_CheckExact

// CPython: Include/listobject.h (public header)
#define PyList_CheckExact(op) Py_IS_TYPE((op), &PyList_Type)

Faster than PyList_Check (which allows subclasses) because it avoids the MRO walk.

gopy notes

_PyList_ITEMS maps to list.items (a []*Object slice in gopy). PyList_GET_ITEM maps to list.items[i] (direct slice indexing, no bounds check in performance-critical paths). PyList_SET_ITEM maps to list.items[i] = v with no reference counting (GC handles it).