Python中的垃圾回收三个知识点(2属性+1方案)。

以引用计数为主,分代收集为辅。引用计数的缺陷是循环引用的问题。(解决循环引用的问题就是直接导入模块名或者延迟导入,或者直接使用弱引用)。

ps:弱引用概念就是一个对象指针,它不会增加它的引用计数.使用弱引用可以当作原始对象一样使用。引用计数也不会增加。

核心思想:在Python中,如果一个对象的引用数为0,Python虚拟机就会回收这个对象的内存。

引用计数:

  引用计数+1的情况:                                                              

    •   对象被创建
    •   对象被引用
    •   对象作为参数传入函数
    •   对象作为元素放入容器中

  引用计数-1的情况:

    •   对象的别名被显式销毁,例如del a
    •   对象的别名被赋予新的对象,例如a=24
    •   一个对象离开它的作用域,例如f函数执行完毕时,func函数中的局部变量(全局变量不会)
    •   对象所在的容器被销毁,或从容器中删除对象

sys.getrefcount(a)可以查看引用计数,但是由于本质上也是将之传入该函数,所以引用计数会在原本值上加1.

垃圾回收机制:

    

  • 垃圾回收后的对象会放在gc.garbage列表里面
  • gc.collect()会返回不可达的对象数目,一般一个对象会有它本身和它的dict属性。会计算对象个数双倍的值。
    • 有三种情况会触发垃圾回收:
    • 1.调用gc.collect(),
      2.当gc模块的计数器达到阀值的时候。
      3.程序退出的时候

  分代收集gc模块重点:

    gc.set_threshold    设置自动执行垃圾回收的频率。当前默认阈值设为(700, 10, 10)。#threshold0是在0级进行垃圾收集之前必须达到的分配数和取消分配数之差。thresholdl是在扫描1级之前必须进行的0级收集数量。threshold2是在收集2级垃圾之前必须进行的1级收集数量。

    gc.collect     显式进行垃圾回收,可以输入参数,参数为可迭代对象

 

对于阈值的0级1级2级的解释说法:

  分代收集的思想就是活的越久的对象,就越不是垃圾,回收的频率就应该越低。所以当Python发现进过几次垃圾回收该对象都是reachable,就将该对象移到二代中,以此类推。那么Python中又是如何检查各个代是否达到阀值的呢?Python中每次会从三代开始检查,如果三代中的对象大于阀值将同时回收3,2,1代的对象。如果二代的满足,将回收2,1代中的对象,设计的是如此的美。

应用注意:

    • 项目中避免循环引用
    • 引入gc模块,启动gc模块的自动清理循环引用的对象机制
    • 由于分代收集,所以把需要长期使用的变量集中管理,并尽快移到二代以后,减少GC检查时的消耗
    • gc模块唯一处理不了的是循环引用的类都有__del__方法,所以项目中要避免定义__del__方法,如果一定要使用该方法,同时导致了循环引用,需要代码显式调用gc.garbage里面的对象的__del__来打破僵局。

    

 

 

 

posted on 2019-11-28 12:26  hole_cheng  阅读(129)  评论(0编辑  收藏  举报