__del__方法和垃圾回收机制分析

python采用引用计数为主,标记-清除(Mark-Sweep)和分代清除为辅的机制,其中标记-清除和分代回收主要是为了处理循环引用的难题。
引用计数算法

  • 思想:
    python中一切皆为对象,对象的核心就是一个结构体PyObject,里面包含引用计数器ob_refcnt,当对象增加一个引用时,ob_refcnt+1;当引用它的对象被删除时,ob_refcnt-1;当引用计数ob_refcnt==0时,对象的生命结束。

  • 优点:
    简单
    实时性:当某个对象的引用计数为0时,内存马上就会被回收;不像其他需要等待特定的时机来进行垃圾回收。这样也带来了另一个好处:垃圾回收的时间也分摊到了平时。

  • 缺点:
    维护引用计数,消耗资源
    致命的缺陷: 循环引用

class Student:
    def __del__(self):
        print('销毁对象{0}'.format(self))

s1 = Student()
s2 = Student()
del s2
print('over')

结果:
销毁对象<main.Student object at 0x000001DEB748B710>
over
销毁对象<main.Student object at 0x000001DEB73C3FD0>
首先销毁s2对象,程序调用结束后对象s1引用次数为0 程序自动销毁对象

# 循环引用的例子
list1 = []
list2 = []
list1.append(list2)  # list1引用list2
list2.append(list1)  # list2引用list1

list1和list2除了引用了对方,没有其他的引用,实际上,它们需要被回收,但是这种情况下采用引用计数机制,引用计数不为0,故不会被回收。面对这种循环引用,引用计数机制束手无策,故后面加入了面向循环引用的标记-清除和分代收集机制。

分代回收算法(以空间换时间)

基于“对象存活的时间越长,越可能不是垃圾,应该越少进行垃圾收集”的思想。
对象等级共分为0、1、2三代,每代对应一个链表,每代有一个代表各代最多允许的对象数量:threshold(默认情况下,generation 0 超过700,或generation 1、generation2超过10,会触发垃圾回收机制)
所有的新建对象都是0代,当一个对象经历过垃圾回收,依然存活,就会被归入下一代对象
generation 0触发,会将generation 0 、1、2依次链接起来再清理
generation 1触发,会将generation 1、 2依次链接起来再清理
generation 2触发,只会清理自己

什么时候会触发垃圾回收?
显式调用gc.collect()
上面说到的三代的计数器阈值threshold达到上限的时候
退出程序的时候

特殊情况,gc模块不能处理:
gc模块唯一处理不了的是循环引用的类带有_del_方法,所以项目中要避免定义_del_方法,如果一定要使用该方法,同时导致了循环引用,需要代码显式调用gc.garbage里面的对象的_del_来打破僵局。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值