2

python | 引用计数器

 1 year ago
source link: https://benpaodewoniu.github.io/2022/12/29/python184/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

python 的内存管理机制是引用计数器为主,标记清除和分代回收为辅 + 缓存机制。

环状双向链表 refchain

python 中创建的任何一个对象都会放在 refchain 中。

当创建一个对象,比如

name = "123"

会同时创建

  • 上一个对象
  • 下一个对象

当然,根据类型的不同,具体的存储也有一点不同,比如,对于 数组来说,会增加

  • items 属性

对于 int 或者其他来说,会增加

  • value 属性

C 语言源码

#define PyObject_HEAD PyObject ob_base;
#define PyObject_VAR_HEAD PyVarObject ob_base;

// 宏定义,包含 上一个、下一个,用于构造双向链表
#define _PyObject_HEAD_EXTRA
struct _object *_ob_next;
struct _object *_ob_prev;

typedef struct _object{
_PyObject_HEAD_EXTRA // 用于构造双向链表
Py_ssize_t ob_refcnt; // 引用计数器
struct _typeobject *ob_type; // 数据类型
}PyObject;

typedef struct{
PyObject ob_base; //PyObject 对象
Py_ssize_t ob_size; // 元素个数
}PyVarObject;

对于不同的类型,会创建不同的结构体

float 类型

typedef struct{
PyObject_HEAD
double ob_fval;
}PyFloatObject;
  • data = 3.14 会创建
    • _ob_next = refchain 下一个对象
    • _ob_prev = refchain 上一个对象
    • ob_refcnt = 1
    • ob_type = float
    • ob_fval = 3.14

其他类型会有自己的结构体。

python 程序运行时,会根据数据类型的不同找到其对应的结构体,根据结构体的字段来进行创建相关的数据,然后将对象添加到 refchain 双向链表中。

C 源码中有两个关键结构体

  • PyObject
  • PyVarObject

引用计数器

对象中的 ob_refcnt 就是引用计数器,值默认为 1。当有其他变量引用的时候,引用计数器会发生变化。

a = 999 # ob_refcnt = 1
b = a # ob_refcnt = 2
del a # ob_refcnt = 1

当引用计数器为 0 时,无对象使用,则会进行垃圾回收。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK