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
| Lines | Symbol | Role |
|---|---|---|
| 1-15 | PyListObject struct | Internal layout: ob_item, allocated |
| 16-36 | _PyList_ITEMS, PyList_GET_SIZE, PyList_GET_ITEM, PyList_SET_ITEM | Unsafe 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).