主页 > 知识库 > Python源码学习之PyType_Type和PyBaseObject_Type详解

Python源码学习之PyType_Type和PyBaseObject_Type详解

热门标签:梅州外呼业务系统 北京电信外呼系统靠谱吗 百度地图标注位置怎么修改 老人电话机器人 无锡客服外呼系统一般多少钱 地图标注视频广告 高德地图标注是免费的吗 大连crm外呼系统 洪泽县地图标注

PyType_Type和PyBaseObject_Type

PyObject和PyTypeObject内容的最后指出下图中对实例对象类型对象的理解是不完全正确的,

浮点类型对象全局唯一,Python在C语言层面实现过程中将其定义为一个全局静态变量,定义于Object/floatobject.c中,命名为PyFloat_Type

PyTypeObject PyFloat_Type = {
    PyVarObject_HEAD_INIT(PyType_Type, 0)
    "float",
    sizeof(PyFloatObject),
    0,
    (destructor)float_dealloc,                  /* tp_dealloc */

    // ...
    (reprfunc)float_repr,                       /* tp_repr */

    // ...
};
  • 第2行使用初始化ob_refcntob_type以及ob_size三个字段,PyVarObject_HEAD_INIT的定义可以参考博文1.4.3节的内容。
  • 第3行将tp_name字段初始化成类型名称"float"
  • 再往下是各种操作的函数指针

ob_type指针指向PyType_Type,这也是一个静态定义的全局变量。代表“类型的类型” 的type对象就是PyType_Type

一. 类型的类型—PyType_Tpye(type的实体)

上文中,float类型对象在底层实现过程中对应PyFloat_Type全局静态变量。Python类型是一种对象,也有自己的类型,即Python中的type。

>>> float.__class__
class 'type'>

自定义类型也遵循同样的规则,

>>> class Foo(object):
...     pass
...
>>> Foo.__class__
class 'type'>

在查看PyFloat_Type代码实现时,ob_type字段指向的PyType_Type就是type的实现。在Object/typeobject.c中定义,

PyTypeObject PyType_Type = {
    PyVarObject_HEAD_INIT(PyType_Type, 0)
    "type",                                     /* tp_name */
    sizeof(PyHeapTypeObject),                   /* tp_basicsize */
    sizeof(PyMemberDef),                        /* tp_itemsize */
    (destructor)type_dealloc,                   /* tp_dealloc */

    // ...
    (reprfunc)type_repr,                        /* tp_repr */

    // ...
};
  • 内建类型和自定义类的PyTypeObject对象都是通过PyType_Type创建PyType_TypePyTypeObject的一个实例。
  • PyType_Type是类型机制中至关重要的对象,是所有类型的类型,称为元类型
  • 第2行代码处PyType_Type将自身的ob_type字段指向它自己。
>>> type.__class__
class 'type'>
>>> type.__class__ is type
True

由此,以float为例,可以绘制一个更完善但是并不完全正确的实例对象和类型对象在内存中的关系图,

二. 类型之基—PyBaseObject_Type(object的实体)

上一节中红色标记的语句,并不完全正确是因为思考过程中忽略了object对象的存在。

object是另一个特殊的类型,是所有类型的基类。同样可以通过PyFloat_Typetp_base字段顺藤摸瓜找到。然而,在源码的第2行的PyVarObject_HEAD_INIT定义中,该字段并没有初始化,

0,                                          /* tp_base */

更进一步查找代码中PyFloat_Type出现的地方,在Object/object.c中发现如下代码,

if (PyType_Ready(PyFloat_Type)  0)
    Py_FatalError("Can't initialize float type");

创建类型对象过程中,需要PyType_Ready方法将tp_base字段初始化,具体如下

int
PyType_Ready(PyTypeObject *type)
{
    // ...

    base = type->tp_base;
    if (base == NULL  type != PyBaseObject_Type) {
        base = type->tp_base = PyBaseObject_Type;
        Py_INCREF(base);
    }

    // ...
}

PyFloat_Type中的tp_base字段初始化成PyBaseObject_Type,它就是object背后的实体,其源码定义为,

PyTypeObject PyBaseObject_Type = {
    PyVarObject_HEAD_INIT(PyType_Type, 0)
    "object",                                   /* tp_name */
    sizeof(PyObject),                           /* tp_basicsize */
    0,                                          /* tp_itemsize */
    object_dealloc,                             /* tp_dealloc */

    // ...
    object_repr,                                /* tp_repr */
};

源码中ob_type字段指向PyType_Type这与下方object在 Python中的测试代码相吻合,

>>> object.__class__
class 'type'>

此外,PyType_Ready函数初始化PyBaseObject_Type时,不设置tp_base字段。 因为继承链必须有一个终点,否则沿着继承链查找时会陷入死循环。

>>> print(object.__base__)
None

由此,得到了实例对象和类型对象在内存中完整的关系图。以float为例,

到此这篇关于Python源码学习之PyType_Type和PyBaseObject_Type详解的文章就介绍到这了,更多相关PyType_Type和PyBaseObject_Type内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
  • Python源码学习之PyObject和PyTypeObject
  • Python源码解析之List
  • python源码剖析之PyObject详解
  • python opencv人脸识别考勤系统的完整源码
  • python 制作手机归属地查询工具(附源码)
  • python基于tkinter制作无损音乐下载工具(附源码)
  • Python bsonrpc源码解读
  • Python制作脚本帮女朋友抢购清空购物车

标签:岳阳 清远 吉林 长春 泉州 怒江 安庆 洛阳

巨人网络通讯声明:本文标题《Python源码学习之PyType_Type和PyBaseObject_Type详解》,本文关键词  Python,源码,学,习之,PyType,;如发现本文内容存在版权问题,烦请提供相关信息告之我们,我们将及时沟通与处理。本站内容系统采集于网络,涉及言论、版权与本站无关。
  • 相关文章
  • 下面列出与本文章《Python源码学习之PyType_Type和PyBaseObject_Type详解》相关的同类信息!
  • 本页收集关于Python源码学习之PyType_Type和PyBaseObject_Type详解的相关信息资讯供网民参考!
  • 推荐文章