Skip to main content

Modules/arraymodule.c

Source:

cpython 3.14 @ ab2d84fe1023/Modules/arraymodule.c

Modules/arraymodule.c implements the array.array type: a mutable sequence of items all of the same C primitive type. Unlike list, every element is stored directly in a contiguous C buffer rather than as a PyObject*. The file contains the arraydescr type table, memory management, the full sequence API, the buffer protocol implementation, and binary I/O helpers.

Map

LinesSymbolRole
1-200arraydescr, type tablePer-typecode descriptor with pack/unpack functions
201-500arrayobject, newarrayobjectStruct and constructor; validates typecode
501-900sequence methodsarray_append, array_extend, array_insert, array_pop
901-1300array_frombytes, array_tobytesBinary import/export
1301-1700array_fromfile, array_tofileFile-based I/O
1701-2100buffer protocolarray_buffer_info, getbuffer, releasebuffer
2101-2500type wiringPyArray_Type, module init

Reading

arraydescr type table

Each entry in descriptors[] maps a typecode character (b, B, h, H, i, I, l, L, q, Q, f, d) to its item size and pack/unpack functions. The pack function converts a Python object to raw bytes in the buffer; unpack does the reverse.

// Modules/arraymodule.c:1 arraydescr (entry for 'd')
static const arraydescr descriptors[] = {
{'b', 1, b_getitem, b_setitem, "b"},
{'h', sizeof(short), h_getitem, h_setitem, "h"},
{'i', sizeof(int), i_getitem, i_setitem, "i"},
{'d', sizeof(double), d_getitem, d_setitem, "d"},
{'\0', 0, NULL, NULL, NULL} /* sentinel */
};

Memory management and resize

array.append and array.extend call array_resize which uses PyMem_Realloc on the internal ob_item buffer. The growth factor mirrors list: approximately 1.125x plus a constant, amortizing reallocations.

// Modules/arraymodule.c:501 array_append_impl
static PyObject *
array_append_impl(arrayobject *self, PyObject *v)
{
Py_ssize_t n = Py_SIZE(self);
if (array_resize(self, n + 1) == -1) return NULL;
return (*self->ob_descr->setitem)(self, n, v);
}

Buffer protocol

getbuffer exposes the raw ob_item buffer using the Py_buffer protocol. This allows zero-copy passing of array contents to C extensions, ctypes, struct.pack_into, and NumPy. The format string ("d" for double, "i" for int, etc.) comes from ob_descr->formats.

// Modules/arraymodule.c:1701 array_buffer_getbuf
static int
array_buffer_getbuf(arrayobject *self, Py_buffer *view, int flags)
{
view->buf = self->ob_item;
view->len = Py_SIZE(self) * self->ob_descr->itemsize;
view->format = (char *)self->ob_descr->formats;
view->itemsize = self->ob_descr->itemsize;
view->ndim = 1;
view->shape = &view->len; /* adjusted below */
view->strides = &view->itemsize;
return 0;
}

Binary I/O

array.frombytes(buf) appends items parsed from a bytes-like object. array.tobytes() returns the raw buffer as bytes. fromfile(f, n) reads exactly n items from a binary file object and appends them; it raises EOFError if fewer than n items are available.

gopy notes

Not yet ported. The planned package path is module/array/. The Go equivalent would use a []byte backing slice with typed views (cast via unsafe.Slice), matching the buffer-protocol semantics for zero-copy interop.