从源码理解PyVarObject与PyObject的区别

1. 引入

我们知道PyObject是python中所有对象的基类,但从源码中还可以看到另一个对象的定义PyVarObject,那PyVarObject又是什么呢?PyVarObject和PyObject有什么区别呢?

2. PyVarObject的源码

从参考2中,我们可以看到 PyObject 与 PyVarObject 的源码如下:

// _PyObject_HEAD_EXTRA 是双向链表的前驱、后继指针定义
#define _PyObject_HEAD_EXTRA            \
    struct _object *_ob_next;           \
    struct _object *_ob_prev;

typedef struct _object {
    _PyObject_HEAD_EXTRA//链表前驱、后继指针
    Py_ssize_t ob_refcnt;//引用计数
    PyTypeObject *ob_type;//类型指针
} PyObject;

typedef struct {
    PyObject ob_base;//PyObject对象
    Py_ssize_t ob_size;//对象的size
} PyVarObject;

从中可以看到,PyVarObject只是在PyObject的基础上,增加了一个ob_size,也就是对象的size。

3. 定长对象与变长对象

从参考1中,python中的对象分为两种:定长对象与变长对象。

定长对象,是不同对象占用的内存大小一样的对象,比如 int。

变长对象,则不同对象占用的内存大小可能不一样,比如string,list和dict。不同字符串的长度可能都不一样,这就是变长对象。

参考1中给出了如下图片,非常便于理解这两个概念:

在这里插入图片描述

4. 结论

定长对象(比如int),是基于PyObject来定义的;而变长对象(比如string),是基于PyVarObject来实现的。

5. 参考

  1. 陈儒,python源码解析
  2. PyObject源码,https://github.com/python/cpython/blob/3.10/Include/object.h#L105

版权声明:本文为ybdesire原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。