聊聊Python垃圾回收机制

Python的垃圾回收机制主要是以引用计数为主和分代回收为辅的结合机制,当对象的引用计数为0时,对象就会被销毁掉。

引用计数

+1的情况

  1. 对象创建时
num = 1
print(sys.getrefcount(num))

print: 187
复制代码

这里23这个对象并没有在内存中创建,因为Python启动解释器的时候会创建一个小整数池,-5~256之间的这些对象,会被自动创建加载到内存中等待调用,num=1只是给这个整数的增加了一个引用

  1. 对象被引用
num = 1
num1 = num
print(sys.getrefcount(num))
print(sys.getrefcount(num1))

print: 188
       188
复制代码
  1. 对象被作为参数,传入到一个函数中
def temp_print(a):
    print(sys.getrefcount(a))

num = 1
num1 = num
temp_print(num)
print(sys.getrefcount(num))
print(sys.getrefcount(num1))

190
188
188
复制代码

传入函数的时候会增加一次引用,执行完毕后又会减少一次引用

4。 对象作为一个元素,存储到容器中

def temp_print(a):
    print(sys.getrefcount(a))

num = 1
num1 = num
temp_print(num)
num_list = [num, num1]
print(sys.getrefcount(num))
print(sys.getrefcount(num1))

190
190
190
复制代码

-1的情况

  1. 对象的别名被赋予新的对象
num = 1
num1 = num
print(sys.getrefcount(num))
num1 = 2
print(sys.getrefcount(num))

188
187
复制代码
  1. 对象的别名被销毁
num = 1
num1 = num
print(sys.getrefcount(num))
del num1
print(sys.getrefcount(num))

188
187
复制代码
  1. 一个对象离开了它的作用域
  2. 对象所在的容器被销毁,或从容器中删除对象
num = 1
num1 = num
data_num = [num, num1]
print(sys.getrefcount(num))
del data_num
print(sys.getrefcount(num))

190
188
复制代码

标记删除

主要是解决循环引用的数据,由于它的引用大于0,所以不会回收

num = ["hello", "world"]
num1 = ["hi", "are", "you"]
print(sys.getrefcount(num))
print(sys.getrefcount(num1))
num.append(num1)
num1.append(num)
print(sys.getrefcount(num))
print(sys.getrefcount(num1))
del num
del num1
复制代码

由于删除后num num1的引用次数仍然为1,所以不会删除
标记删除就是为了解决这个循环引用的无法删除
步骤:

  1. 对删除操作后的每个引用-1, 此时num, num1的引用为0,把他们放到死亡容器里面,如果它的引用还是大于0就放到存活容器里
  2. 遍历存活容器,查看是否有的存活容器引用了死亡容器的对象,如果有的话,就把该对象从死亡容器内取出,放到存活容器里。
  3. 讲死亡容器里的所有对象全部删除

分代回收

  1. 新创建的对象为0代
  2. 每执行一个标记删除,存活的对象就加1
  3. 代数越高的对象,进行标记删除的时间间隔就越长

讲系统中的全部内存块依据其存活时间划分不同的集合,每个集合就成为一个“代”,垃圾收集的频率随着“代”的存活时间的增大而减少

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享