Skip to main content

Lib/collections/__init__.py (part 5)

Source:

cpython 3.14 @ ab2d84fe1023/Lib/collections/__init__.py

This annotation covers the deque type (implemented in C; this annotation covers its Python-visible interface). See lib_collections4_detail for OrderedDict, Counter, and defaultdict.

Map

LinesSymbolRole
1-60deque.__init__Initialize from an iterable with optional maxlen
61-140deque.append / deque.appendleftO(1) adds to either end
141-220deque.pop / deque.popleftO(1) removes from either end
221-300deque.rotateRotate n steps to the right
301-400maxlen semanticsBounded deque — evict on append

Reading

deque internal structure

// CPython: Modules/_collectionsmodule.c:60 (deque internals)
/* deque is implemented as a doubly-linked list of fixed-size blocks.
BLOCKLEN = 64 items per block.
leftblock / leftindex: left end
rightblock / rightindex: right end
Each block is a C array; when a block is full, a new one is allocated. */
typedef struct BLOCK {
struct BLOCK *leftlink;
PyObject *data[BLOCKLEN];
struct BLOCK *rightlink;
} Block;

The block-based structure gives O(1) amortized append/pop at both ends with good cache behavior. Random access is O(n) since there's no index mapping.

deque.append

// CPython: Modules/_collectionsmodule.c:280 deque_append
static PyObject *
deque_append(dequeobject *deque, PyObject *item)
{
if (deque->rightindex == BLOCKLEN - 1) {
/* Right block is full: allocate a new one */
Block *b = newblock();
b->leftlink = deque->rightblock;
deque->rightblock->rightlink = b;
deque->rightblock = b;
deque->rightindex = -1;
}
Py_INCREF(item);
deque->rightblock->data[++deque->rightindex] = item;
deque->len++;
if (deque->maxlen >= 0 && deque->len > deque->maxlen)
deque_popleft(deque, NULL);
Py_RETURN_NONE;
}

When maxlen is set, appending to a full deque automatically pops from the opposite end. appendleft/popleft mirror this logic on the left side.

deque.rotate

// CPython: Modules/_collectionsmodule.c:520 deque_rotate
static PyObject *
deque_rotate(dequeobject *deque, PyObject *const *args, Py_ssize_t nargs)
{
Py_ssize_t n = 1;
if (nargs && !_PyArg_ParseStack(args, nargs, "n:rotate", &n)) return NULL;
if (Py_SIZE(deque) == 0 || n == 0) Py_RETURN_NONE;
if (n > 0) {
/* Move n items from right to left */
for (Py_ssize_t i = 0; i < n; i++) {
PyObject *item = deque_pop(deque, NULL);
deque_appendleft(deque, item);
Py_DECREF(item);
}
} else {
/* Move |n| items from left to right */
...
}
Py_RETURN_NONE;
}

deque.rotate(1) moves the rightmost element to the front. rotate(-1) is the reverse. Used to implement circular buffers.

gopy notes

deque is objects.Deque in objects/deque.go backed by a Go doubly-linked list of fixed-size arrays (BLOCKLEN = 64). append/appendleft allocate new blocks when full. maxlen enforcement evicts from the opposite end. rotate moves elements by calling pop/appendleft.