¿Cómo implementa Cpython su tipo Objetos, es decir, el tipo de tipo siempre es de tipo?

Entiendo que todo en Python es un Objeto y que el ‘tipo’ (o clase) de estos objetos es ‘tipo’. Además, el tipo de tipo también es el tipo en sí. (como se explica muy bien aquí )

Lo que no entiendo es cómo se implementa esta referencia circular. Así que miré aquí . Para citar la parte que podría explicar lo que estoy buscando:

PyTypeObject* PyObject.ob_type 

Este es el tipo de letra, en otras palabras, su metatipo. Se inicializa mediante el argumento de la macro PyObject_HEAD_INIT, y su valor normalmente debería ser & PyType_Type. Sin embargo, para los módulos de extensión cargables dinámicamente que deben ser utilizables en Windows (al menos), el comstackdor se queja de que este no es un inicializador válido. Por lo tanto, la convención es pasar NULL a la macro PyObject_HEAD_INIT e inicializar este campo explícitamente al inicio de la función de inicialización del módulo, antes de hacer cualquier otra cosa. Esto se hace típicamente así:

 Foo_Type.ob_type = &PyType_Type; 

Dado que C no está basado en OOP, entiendo que cuando uno crea una clase, puede tener un atributo para señalar al objeto en sí como su propia clase. Estoy seguro de que mi falta de comprensión aquí me ha llevado a un estado de confusión, ¿alguien puede señalar si esta es una práctica habitual en el diseño de otros lenguajes de script o algún tipo de patrón, si alguien puede arrojar algo de luz sobre esto? Estaré agradecido por ello.

EDIT: aquí descubrí que:

 PyObject* PyType_Type 

Este es el objeto de tipo para los objetos de tipo; es el mismo objeto que type y types.TypeType en la capa Python.

¿Como es eso?

El código que define PyType_Type.ob_type = & PyType_Type implica un par de indirectas. Todo comienza en la función _Py_ReadyTypes() cuando llama a PyType_Ready(&PyType_Type) . Antes de llamar a la función, los miembros tp_base y ob_type son NULL . La función primero establece type->tp_base en &PyBaseObject_Type (que es el object en el espacio de Python) y luego establece type->ob_type = PyBaseObject_Type.ob_type . El código usa Py_TYPE() que es solo una macro para ob->ob_type . Dado que el tipo de objeto es tipo, el código establece el tipo de tipo a tipo.

Ahora tu tienes:

 >>> type.__bases__ (,) >>> type(object)  >>> type(type(object))  

La definición hace que type sea una instancia de objeto más el objeto y una instancia de tipo.

 >>> isinstance(type, object) True >>> isinstance(object, type) True >>> isinstance(type, type) True 

El código de inicialización de tipo es mucho más fácil de entender en el pseudocódigo de Python:

 # object's class is type object.__class__ = type # PyType_Ready(type) sets: type.__bases__ = (object,) type.__class__ = type(object)