E0adc6177d2d6ce732c6990986436265
番外:PyBaseObject_Type继承流程

番外:PyBaseObject_Type继承流程

本文算是一个番外补充篇

之前有读者朋友反馈在阅读外《Python 对象与类》之后有点迷糊,不知道PyBaseObject_Type是个啥。

同时有认真的读者阅读了CPython中的代码,发现PyInt_Type中的tp_base为空,并不是如下图所示继承自PyBaseObject_Type

好,首先我们来看下PyInt_Type的结构体定义,确实如读者所述,tp_base为空。同时我们可以发现其对应的tp_alloc, tp_init函数也为空。难道说PyIntObject不需要分配空间了吗?

PyTypeObject PyInt_Type = {
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
    "int",
    sizeof(PyIntObject),
    0,
    (destructor)int_dealloc,                    /* tp_dealloc */
    (printfunc)int_print,                       /* tp_print */
    0,                                          /* tp_getattr */
    0,                                          /* tp_setattr */
    (cmpfunc)int_compare,                       /* tp_compare */
    (reprfunc)int_to_decimal_string,            /* tp_repr */
    &int_as_number,                             /* tp_as_number */
    0,                                          /* tp_as_sequence */
    0,                                          /* tp_as_mapping */
    (hashfunc)int_hash,                         /* tp_hash */
    0,                                          /* tp_call */
    (reprfunc)int_to_decimal_string,            /* tp_str */
    PyObject_GenericGetAttr,                    /* tp_getattro */
    0,                                          /* tp_setattro */
    0,                                          /* tp_as_buffer */
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |
        Py_TPFLAGS_BASETYPE | Py_TPFLAGS_INT_SUBCLASS,          /* tp_flags */
    int_doc,                                    /* tp_doc */
    0,                                          /* tp_traverse */
    0,                                          /* tp_clear */
    0,                                          /* tp_richcompare */
    0,                                          /* tp_weaklistoffset */
    0,                                          /* tp_iter */
    0,                                          /* tp_iternext */
    int_methods,                                /* tp_methods */
    0,                                          /* tp_members */
    int_getset,                                 /* tp_getset */
    0,                                          /* tp_base */    注意这一行
    0,                                          /* tp_dict */
    0,                                          /* tp_descr_get */
    0,                                          /* tp_descr_set */
    0,                                          /* tp_dictoffset */
    0,                                          /* tp_init */
    0,                                          /* tp_alloc */
    int_new,                                    /* tp_new */
};

答案当然不是,关键在于Python加载PyIntObject的过程中隐式帮我们完成了绑定基类PyBaseObject_Type

这里的内容开始牵涉到Python虚拟机了,有点进度超前,本文仅仅大致描述过程。

什么是Python加载过程?

熟悉Python的朋友肯定知道,我们在日常开发过程中会使用大量的第三方库,比如numpy

那么在使用前,我们会键入如下代码:

import numbpy as np

上述这句代码,其实就是动态加载一个模块。但是对于诸如PyStringObject, PyIntObject,它们属于Python的内建模块:

bltinmodule.c中可以发现如下节选代码:

top Created with Sketch.