Python源码分析:PyObject对象的起源与多态的实现

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python源码分析:PyObject对象的起源与多态的实现相关的知识,希望对你有一定的参考价值。

在python中一切皆是对象,那么这种机制是如何实现的呢?下面就让我们从python的老巢“源码”来看看这个神秘的机制。

typedef struct _object {

PyObject_HEAD

 } PyObject;

 

typedef struct {

PyObject_VAR_HEAD

} PyVarObject;

 

看到上面这两个结构体了吗?它们就是万源之源,所有python对象的祖先,为什么有两个祖先呢?这就要从现实时间的数据对象谈起,我们有些数据,像数字、固定矩阵这类数据其元素个数是固定不变的,而像字符串、集合、字典这类数据其元素个数是会上下浮动的。这样python的发明者在设计python时就为这两类数据创造了两个祖先(像人有男人与女人一样,好像不太确切,但本质就是有两个祖先了):定长数据类型与变长数据类型。

这两个结构体里面的两个变量,其实都是些宏。从源中我们可以找到这些宏的展开:

#define PyObject_HEAD \

_PyObject_HEAD_EXTRA \

Py_ssize_t ob_refcnt; \

 

struct _typeobject *ob_type;

#define PyObject_VAR_HEAD \

PyObject_HEAD \

Py_ssize_t ob_size;

看得出来,类型多了的这个ob_size就说明了它的变长特性(元素的个数)。

下面我们来仔细看看PyObject_HEAD这个宏的内容:

_PyObject_HEAD_EXTRA:这个宏展开时要么是双向链表的前后指针要么是空,是在跟踪所有对象时使用:想像一下,一个双向链表把python所有的对象串联起来的场景,好宏大呀!

ob_refcnt:这个属性记录该对象被他人引用的次数(后面发现,这个东西是用来进行内存管理的:引用计数式的垃圾回收机制)

ob_type:这个玩意是个重头戏,它实现了python的多态(何谓多态:对于不同的类型的对象,相同名称的方法其表现行为不同),何以见得呢?下面就让我们重点分析下这个ob_type,首先看看ob_type的原型是什么:

typedef struct _typeobject {

PyObject_VAR_HEAD

const char *tp_name;

Py_ssize_t tp_basicsize, tp_itemsize;

printfunc tp_print;

。。。

 

PyNumberMethods *tp_as_number;

PySequenceMethods *tp_as_sequence;

PyMappingMethods *tp_as_mapping;

。。。

} PyTypeObject;

这个结构体在源代码中整整占了84行,天呢!它是个什么,这么多内容。我们重点看几个字段:

PyObject_VAR_HEAD

:嗯,这不是变长数据类型它老祖先里的头‘骨’吗?怎么这里还有呢?没错,你猜对了,我们指明某个对象类型的对象原型 PyTypeObject也是一个对象。至于为什么是变长类型的对象祖先的头’骨‘,还没搞清楚^0^。

tp_print:多态的内部原理开始显露了吧!就是通过这个type对象来为具体不同的对象提供不同的方法实现,尽量方法名字都一样。

PyNumberMethods,PySequenceMethods,PyMappingMethods:其实和上面这个tp_print一样,只不它们是个函数族(由函数集构成),类数字操作(比如支持+-×/)、类序列操作(比如[n:m]切片操作)、字典操作(比如dict[key]操作)。

下面就int类型对象对上面这些原理进行验证:

typedef struct {

PyObject_HEAD

long ob_ival;

} PyIntObject;

这就是我们的int类型对象,其头部呢?在python源中可以看出,用一系列宏来实现头部的初始化:

#define PyObject_HEAD_INIT(type) \

_PyObject_EXTRA_INIT \

1, type,

这里的type,从源码中看出,有一个PyType_Type类型,它就是那个描述类型的类型的对象。有点绕了,但是仔细理解下来,也没什么,无外乎:一个int数据,有一个专门描述int类型数据的类型对象,但是不光有int类型的类型对象还有string类型的类型对象。那么就需要有一个要对象来描述这些类型对象,这就是PyType_Type,也就是它可以测试一个对象是不是类型对象。

以上是关于Python源码分析:PyObject对象的起源与多态的实现的主要内容,如果未能解决你的问题,请参考以下文章

python int的源码分析

从源码理解PyVarObject与PyObject的区别

从源码理解PyVarObject与PyObject的区别

从源码理解PyVarObject与PyObject的区别

python3 整数类型PyLongObject 和PyObject源码分析

python对象pyObject的源码实现