"""
环状双向链表 refchain
内部创建一些数据(上一个对象,下一个对象,类型,引用个数,等等)
在C语言代码中如何体现每个对象都有相同的值:PyObject结构体(4个值)
有多个元素组成的对象:PyObject结构体(4个值) + ob_size
"""
name = "peter"
age = 22
hobby = ["篮球","咖啡"]
data = 3.14

1. """引用计数器"""
v1 = 3.14
v2 = 999
v3 = (1,2,3)
当python程序运行时,会根据数据类型的不同找到其对应的结构体,根据结构体中的字段来进行创建相关的数据
然后将对象添加到refchain双向链表中
在C语言源码中有两个关键的结构体:PyObject,PyVarObject
每个对象中都有ob_refcnt就是引用计数器,值默认为1,当有其他变量引用对象时,引用计数器会发生变化
a = 9999
b = a
a = 9999
b = a
del b
"""
当一个对象的引用计数器为0时,意味着没有人使用这个对象,这个对象就是垃圾,垃圾回收
回收:1. 对象从refchain链表移除;2. 将其对象销毁,内存归还
缺点:1. 维护引用计数需要消耗一定资源;2. 循环引用时无法回收
"""
2. 标记清除:为了解决引用计数器循环引用的不足
实现:在python的底层再维护一个链表,链表中专门存放那些可能存在循环引用的对象(list/tuple/dict/set)
在python内部,某种情况下触发,会去扫描可能存在循环引用的链表中的每个元素,如果有则让双方的引用计数器-1
;如果时0则垃圾回收
3. 存在问题:1. 什么时候扫描;2. 可能存在循环引用的链表扫描代价大耗时久
分代回收:将可能存在循环引用的对象维护成3个链表
0代:0代中的对象个数达到700个扫描一次
1代:0代扫描10次,则1代扫描一次
2代:1代扫描10次,则2代扫描一次
"""
"""
python缓存:
1). 池(int类型)
为了避免重复创建和销毁一些常见对象,维护池
启动python解释器时,python内部帮我们创建-5,-4,.....257
2). free_list
当一个对象引用计数为0时,按理应该回收,内部不会直接回收而是将对象添加到free_list链表中当缓存
,以后再创建对象时,不再重新开辟内存,而是直接使用free_list
"""
v1 = 3.14 #开辟内存,内部存储结构体中定义几个值,并存到rechain中
del v1 #rechain中移除,将对象添加到free_list中,free_list满了才销毁
v2 = 99.99 #不会重新开辟新内存,去free_list中获取对象,对象内部数据初始化再放到rechain中