Skip to main content

Objects/typeobject.c (part 9)

Source:

cpython 3.14 @ ab2d84fe1023/Objects/typeobject.c

This annotation covers the class creation pipeline. See objects_typeobject8_detail for __subclasshook__, __instancecheck__, and type.__or__.

Map

LinesSymbolRole
1-80type.__prepare__Create the class namespace before executing the body
81-160type.__init_subclass__Hook called after a subclass is created
161-260type.__set_name__Hook called on descriptors when defined in a class
261-360type_new_implThe full class creation path
361-500type_readyInherit slots, fill in defaults

Reading

type.__prepare__

// CPython: Objects/typeobject.c:5080 type_prepare
static PyObject *
type_prepare(PyObject *self, PyObject *const *args, Py_ssize_t nargs,
PyObject *kwnames)
{
/* Return the namespace dict for the class body.
Called before the class body is executed.
Metaclass.prepare(name, bases, **kwargs) */
return PyDict_New();
}

type.__prepare__ returns a plain dict. ABCMeta.__prepare__ and OrderedMeta.__prepare__ can return custom mappings (like OrderedDict) that preserve insertion order or track method definitions.

type.__init_subclass__

// CPython: Objects/typeobject.c:5140 type_init_subclass
static PyObject *
type_init_subclass(PyTypeObject *cls, PyObject *kwds)
{
/* Called on the base class when a new subclass is created.
class Sub(Base, kwarg=val): ...
→ Base.__init_subclass__(kwarg=val) is called */
return PyObject_CallMethodObjArgs(
(PyObject *)cls, str___init_subclass__, kwds, NULL);
}

__init_subclass__ runs after the subclass body is executed and the type is created. Plugins use it: class MyPlugin(Plugin, category='foo') calls Plugin.__init_subclass__(category='foo') which can register the plugin.

type.__set_name__

// CPython: Objects/typeobject.c:5200 type_set_name_in_class
static int
type_set_name_in_class(PyObject *cls, PyObject *name, PyObject *value)
{
/* If value has __set_name__, call it: value.__set_name__(cls, name) */
PyObject *set_name = PyObject_GetAttr(value, str___set_name__);
if (set_name == NULL) {
if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
PyErr_Clear();
return 0;
}
return -1;
}
return PyObject_CallFunctionObjArgs(set_name, cls, name, NULL) ? 0 : -1;
}

__set_name__ is called for every name-value pair in the class body. Descriptors use it to record the attribute name they were assigned to: class MyDesc: def __set_name__(self, owner, name): self.name = name.

gopy notes

type.__prepare__ is objects.TypePrepare in objects/type.go. For plain type, it returns objects.NewDict(). __init_subclass__ is called in objects.TypeNew after the class body executes. __set_name__ is called in a loop over the namespace by objects.TypeNew.