• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

Python源码学习之PyType_Type和PyBaseObject_Type详解

python 搞代码 4年前 (2022-01-07) 44次浏览 已收录 0个评论
文章目录[隐藏]

今天给大家带来的是关于Python源码的相关知识学习,文章围绕着PyType_Type和PyBaseObje

来源gao!%daima.com搞$代*!码网

ct_Type展开,文中有非常详细的介绍及代码示例,需要的朋友可以参考下

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 Foo(object): ...     pass ... >>> Foo.__class__ 

在查看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__  >>> 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__ 

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

 >>> print(object.__base__) None

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

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

以上就是Python源码学习之PyType_Type和PyBaseObject_Type详解的详细内容,更多请关注gaodaima搞代码网其它相关文章!


搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:Python源码学习之PyType_Type和PyBaseObject_Type详解

喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址