Python垃圾回收

发布时间:2022-03-07 10:22:49 人气:178 作者:多测师

  Python垃圾回收包括引用计数、标记清除和分代回收

  引用计数

  引用计数是一种垃圾收集机制,当一个python对象被引用时,引用计数加 1,当一个对象的引用为0时,该对象会被当做垃圾回收。

  from sys import getrefcount

  l1 = [1, 2, 3]

  print(getrefcount(l1)) # 查看引用计数

  l2 = l1

  print(getrefcount(l2))

  执行结果:

  2

  3

  在使用 getrefcount()的时候,变量作为参数传进去,会多一次引用。

  del语句会删除对象的一个引用。请看下面的例子:

  from sys import getrefcount

  class TestObjectA():

  def __init__(self):

  print("hello!!!")

  def __del__(self):

  print("bye!!!")

  a = TestObjectA()

  b = a

  c = a

  print(getrefcount(c))

  del a

  print(getrefcount(c))

  del b

  print(getrefcount(c))

  del c

  print("666")

  执行结果:

  hello!!!

  4

  3

  2

  bye!!!

  666

  方法__del__ 的作用是当对象被销毁时调用。其中del a删除了变量a,但是对象TestObjectA仍然存在,它还被b和c引用,所以不会被回收,引用计数为0时会被回收。上面的例子中,将a,b,c都删除后引用的对象被回收(打印“666”之前)。

Python垃圾回收

  另外重新赋值也会删除对象的一个引用。

  标记清除

  如果出现了循环引用,引用计数方法就无法回收,导致内存泄漏。先来看下面的例子:

  class TestObjectA(dict):

  def __init__(self):

  print("A: hello!!!")

  def __del__(self):

  print("A: bye!!!")

  class TestObjectB(dict):

  def __init__(self):

  print("B: hello!!!")

  def __del__(self):

  print("B: bye!!!")

  a = TestObjectA()

  b = TestObjectB()

  a['1'] = b

  b['1'] = a

  del a

  del b

  print("666")

  执行结果:

  A: hello!!!

  B: hello!!!

  666

  A: bye!!!

  B: bye!!!

  上面的代码存在循环引用,删除a和b之后,它们的引用计数还是1,仍然大于0,不会被回收(打印“666”之后)。

  标记清除可解决循环引用问题,从根对象(寄存器和程序栈上的引用)出发,遍历对象,将遍历到的对象打上标记(垃圾检测),然后在内存中清除没有标记的对象(垃圾回收)。上面的例子中,a和b相互引用,如果与其他对象没有引用关系就不会遍历到它,也就不会被标记,所以会被清除。

  分代回收

  如果频繁进行标记清除会影响Python性能,有很多对象,清理了很多次他依然存在,可以认为,这样的对象不需要经常回收,也就是说,对象存在时间越长,越可能不是垃圾。

  将回收对象进行分代(一共三代),每代回收的时间间隔不同,其中新创建的对象为0代,如果一个对象能在第0代的垃圾回收过程中存活下来,那么它就被放入到1代中,如果1代里的对象在第1代的垃圾回收过程中存活下来,则会进入到2代。

  gc模块

  以下三种情况会启动垃圾回收:

  ·调用gc.collect():强制对所有代执行一次回收

  · 当gc模块的计数器达到阀值的时候。

  · 程序退出的时候

  gc 模块函数:

  · gc.enable() :启用自动垃圾回收

  · gc.disable():停用自动垃圾回收

  · gc.isenabled():如果启用了自动回收则返回 True。

  · gc.collect(generation=2):不设置参数会对所有代执行一次回收

  · gc.set_threshold(threshold0[, threshold1[, threshold2]]):设置垃圾回收阈值

  · gc.get_count():当前回收计数

  · 垃圾回收启动的默认阈值

  import gc

  print(gc.get_threshold())

  输出:

  (700, 10, 10)

  700是垃圾回收启动的阈值,对象分配数量减去释放数量的值大于 700 时,就会开始进行垃圾回收,每10次0代垃圾回收,会导致一次1代回收;而每10次1代的回收,才会有1次的2代回收。可以使用set_threshold()方法重新设置。

  以上内容为大家介绍了Python垃圾回收,希望对大家有所帮助,如果想要了解更多Python相关知识,请关注多测师。https://www.e70w.com/xwzx/

返回列表
在线客服
联系方式

热线电话

17727591462

上班时间

周一到周五

二维码
线