Skip to main content

Objects/namespaceobject.c (part 2)

Source:

cpython 3.14 @ ab2d84fe1023/Objects/namespaceobject.c

This annotation covers SimpleNamespace comparison and serialization. See objects_namespaceobject_detail for __new__, __init__, __setattr__, __getattr__, and the internal __dict__.

Map

LinesSymbolRole
1-80SimpleNamespace.__repr__namespace(x=1, y=2) representation
81-180SimpleNamespace.__eq__Equality by __dict__ comparison
181-280SimpleNamespace.__reduce__Pickle support
281-350__iter__ / __len__Iterate attribute names (via __dict__)

Reading

SimpleNamespace.__repr__

// CPython: Objects/namespaceobject.c:120 namespace_repr
static PyObject *
namespace_repr(PyObject *ns)
{
/* Produce "namespace(key=value, ...)" sorted by key */
PyObject *d = ((PyNamespaceObject *)ns)->ns_dict;
PyObject *keys = PyDict_Keys(d);
PyList_Sort(keys);
PyObject *pieces = PyList_New(PyList_GET_SIZE(keys));
for (int i = 0; i < PyList_GET_SIZE(keys); i++) {
PyObject *k = PyList_GET_ITEM(keys, i);
PyObject *v = PyDict_GetItem(d, k);
PyList_SET_ITEM(pieces, i, PyUnicode_FromFormat("%S=%R", k, v));
}
PyObject *joined = PyUnicode_Join(_comma_space, pieces);
return PyUnicode_FromFormat("namespace(%S)", joined);
}

Keys are sorted for stable repr output. types.SimpleNamespace(b=2, a=1) prints as namespace(a=1, b=2).

SimpleNamespace.__eq__

// CPython: Objects/namespaceobject.c:200 namespace_richcompare
static PyObject *
namespace_richcompare(PyObject *self, PyObject *other, int op)
{
if (op != Py_EQ && op != Py_NE) {
Py_RETURN_NOTIMPLEMENTED;
}
if (!PyObject_TypeCheck(other, &PyNamespace_Type)) {
Py_RETURN_NOTIMPLEMENTED;
}
PyObject *d_self = ((PyNamespaceObject *)self)->ns_dict;
PyObject *d_other = ((PyNamespaceObject *)other)->ns_dict;
return PyObject_RichCompare(d_self, d_other, op);
}

Two SimpleNamespace objects are equal iff their __dict__s are equal. Only == and != are supported; <, <=, >, >= return NotImplemented.

SimpleNamespace.__reduce__

// CPython: Objects/namespaceobject.c:260 namespace_reduce
static PyObject *
namespace_reduce(PyObject *self, PyObject *Py_UNUSED(ignored))
{
/* Return (type, (), state) where state = __dict__ */
PyObject *ns_dict = ((PyNamespaceObject *)self)->ns_dict;
return PyTuple_Pack(3,
Py_TYPE(self),
PyTuple_New(0),
PyDict_Copy(ns_dict));
}

pickle.dumps(types.SimpleNamespace(x=1)) works because __reduce__ returns the type plus the dict. On unpickling, __init__(**state) restores the attributes.

gopy notes

SimpleNamespace.__repr__ is objects.NamespaceRepr in objects/namespace.go. Key sorting uses Go's sort.Strings. __eq__ delegates to objects.DictEqual. __reduce__ returns a 3-tuple matching the pickle protocol. __iter__ delegates to objects.DictKeys.