The code that defines PyType_Type.ob_type = &PyType_Type involves a couple of indirections. It all starts in the function _Py_ReadyTypes()
when it calls PyType_Ready(&PyType_Type)
. Before the function is called, the members tp_base
and ob_type
are both NULL
. The function first sets type->tp_base
to &PyBaseObject_Type
(which is object
in Python space) and then sets type->ob_type = PyBaseObject_Type.ob_type
. The code uses Py_TYPE()
which is just a macro for ob->ob_type
. Since the type of object is type the code sets the type of type to type.
Now you have:
>>> type.__bases__
(<class 'object'>,)
>>> type(object)
<class 'type'>
>>> type(type(object))
<class 'type'>
The definition makes type an instance of object plus itself and object an instance of type.
>>> isinstance(type, object)
True
>>> isinstance(object, type)
True
>>> isinstance(type, type)
True
The type initialization code is much easier to understand in Python pseudo-code:
# object's class is type
object.__class__ = type
# PyType_Ready(type) sets:
type.__bases__ = (object,)
type.__class__ = type(object)