Skip to main content

Objects/rangeobject.c

cpython 3.14 @ ab2d84fe1023/Objects/rangeobject.c

Objects/rangeobject.c implements Python's built-in range type. All operations are integer-arithmetic-only with no list allocation. The iterator (rangeiterobject) holds a current index and reduces __next__ to a single addition.

Map

LinesSymbolRole
1-100rangeobject struct, range_newConstruction from start/stop/step
101-300range_length_obj, compute_range_lengthO(1) length computation
301-450range_item, range_containsO(1) index and membership
451-580range_richcompareValue-based equality
581-720rangeiterobject, rangeiter_nextLazy iterator

Reading

O(1) length

The length formula is max(0, ceil((stop - start) / step)). For large-integer ranges CPython uses PyLong arithmetic so the length never overflows.

// CPython: Objects/rangeobject.c:154 compute_range_length
static PyObject *
compute_range_length(PyObject *start, PyObject *stop, PyObject *step)
{
/* if step > 0: max(0, (stop - start + step - 1) / step)
if step < 0: max(0, (stop - start + step + 1) / step) */
...
}

O(1) __contains__

Membership is tested by checking divisibility: (value - start) % step == 0 and 0 <= (value - start) // step < length.

// CPython: Objects/rangeobject.c:358 range_contains_long
static int
range_contains_long(rangeobject *r, PyObject *ob)
{
int cmp1, cmp2, cmp3;
PyObject *tmp1 = NULL, *tmp2 = NULL;
/* ob >= start */
cmp1 = PyObject_RichCompareBool(r->start, ob, Py_LE);
...
/* (ob - start) % step == 0 */
...
}

rangeiter_next

The iterator stores index and len. Each __next__ call computes start + index * step, increments index, and returns. When index >= len it raises StopIteration.

// CPython: Objects/rangeobject.c:640 rangeiter_next
static PyObject *
rangeiter_next(rangeiterobject *r)
{
if (r->index < r->len) {
long result = (long)(r->start +
(unsigned long)(r->index++) * r->step);
return PyLong_FromLong(result);
}
return NULL;
}

Rich comparison

Two ranges are equal if and only if they represent the same sequence of values. CPython checks: same length, and if length is non-zero, same first element and (if length > 1) same last element (which determines step).

gopy notes

Not yet ported. range is a built-in type that must live in the core objects layer. The Go struct will hold start, stop, step as *big.Int to handle arbitrary-precision ranges as CPython does.