python对象pyObject的源码实现

Posted ybdesire

tags:

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

1. 引入

在python中,基本数据类型,比如整数,是存储在栈中吗?

答案是否定的,python中的数据,都是对象,对象都存储在堆区。

2. 一切都是对象

在Python的世界中,一切都是对象,一个整数是一个对象,一个字符串也是一个对象。更为奇妙的是,类型也是一种对象,整数类型是一个对象,字符串类型也是一个对象;面向对象理论中的“类”和“对象”,都是通过python内的对象来实现的(摘自参考1)。

为什么是这样呢?

因为cpython中,并没有对象这种机制,所以使用struct来定义了python内的对象。也就是说,python的对象,都是通过c语言的struct来实现的。

3. 对象都在堆区被创建

在cpython源码(Python-3.10.4/Include/object.h)中,明确说明了所有对象都是在堆区申请的内存:

Objects are structures allocated on the heap. Special rules apply to
the use of objects to ensure they are properly garbage-collected.
Objects are never allocated statically or on the stack; they must be
accessed through special macros and functions only.

这里也强调了python内的对象永远不可能在栈区申请内存。

4. 对象的结构

python内的对象,是C语言定义一个名为PyObject的struct(参考2),核心源码如下:

/* Define pointers to support a doubly-linked list of all live heap objects. */
#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;

我们可以看到:

  1. 所有对象都会被组成一个双链表,源码注释中就强调了这个
  2. 对象就是双链表中的一个节点
  3. _ob_prev_ob_next是双链表的前驱、后继节点
  4. ob_refcnt是垃圾回收中的引用计数器,他记录了某个对象被引用的次数,当该数值为0时这个对象就会被垃圾回收器回收
  5. ob_type指向类型对象的指针

5. 有哪些对象

从参考3中,我们可以看到,python中的任何一个类型,都有对应的.h文件来定义这个类型的对象,比如:

  • int对象:intobject.h
  • boolobject.h
  • floatobject.h
  • bytesobject.h
  • listobject.h
  • dictobject.h
  • setobject.h
  • classobject.h

6. 环状双向链表

所有存活的对象,都组成一个环状双向链表(参考4)。双向链表的头指针名为 refchain 。

为什么是双向链表而非单链表呢?

  • 双向链表的优点,在于可以双向索引
  • 那么这里是否真的有必要组成双链表呢?笔者通过全文搜索源码中的双链表前驱指针_ob_prev,发现源码中其实对双链表前驱遍历的使用非常少,所以单纯从python3.10的C源码来看,笔者认为源码中并没有对双链表的优势做太多有价值的使用

5. 总结

本文讲述了:python中一切都是对象(包括int,string,list),对象都保存在堆区,pyObject的源码以及环状双向链表保存所有存活对象。

6. 参考

  1. 陈儒,python源码解析
  2. PyObject源码,https://github.com/python/cpython/blob/3.10/Include/object.h#L105
  3. https://github.com/python/cpython/tree/3.10/Include
  4. refchain,https://github.com/python/cpython/blob/3.10/Objects/object.c#L86

以上是关于python对象pyObject的源码实现的主要内容,如果未能解决你的问题,请参考以下文章

python对象pyObject的源码实现

python源码分析:dict对象的实现

Python内部机制-PyObject对象

从源码理解PyVarObject与PyObject的区别

从源码理解PyVarObject与PyObject的区别

从源码理解PyVarObject与PyObject的区别