内部引用可防止垃圾回收

时间:2012-02-17 13:37:51

标签: python garbage-collection initialization

我正在写一个简单的平台游戏,我发现在删除“幽灵”游戏时实例,它们坚持并且不是垃圾收集。似乎虽然我删除了所有引用,但ghost对象有一些内部引用,阻止它们被垃圾收集。具体来说,它们具有方法切换的属性。

以下代码说明了我的问题:

import weakref

weak_ghosts = weakref.WeakKeyDictionary()

class Ghost(object):
    def __init__(self):
        #pass
        self.switch = {'eat':self.eat, 'sleep':self.sleep}

    def eat(self):
        pass

    def sleep(self):
        pass

ghost = Ghost()
weak_ghosts[ghost] = None
#ghost.switch = {}    # uncomment this line and ghost is successfully removed
del ghost
print "number of ghosts =", len(weak_ghosts)

#output:
number of ghosts = 1

问题:

  1. 究竟发生了什么?
  2. 我应该怎么做以避免这种情况?
  3. 我是否使用正确的方法制作可切换的方法词典?

2 个答案:

答案 0 :(得分:4)

self.switch创建一个循环引用,引用它所属的对象。看看这个:

import weakref

class Ghost(object):
    def __init__(self):
        #pass
        self.switch = {'eat':self.eat, 'sleep':self.sleep}

    def eat(self):
        pass

    def sleep(self):
        pass

ghost = Ghost()

def callback(o):
    print 'callback', o

wref = weakref.ref(ghost, callback)
print 'del ghost'
del ghost
print 'after del ghost'

打印:

del ghost
after del ghost
callback <weakref at 00B55FC0; dead>

因此实际对象刚刚关闭时被清除。

您可以手动运行GC以查看效果。将其添加到上面脚本的末尾:

print 'gc.collect'
import gc
gc.collect()
print 'after gc.collect'

现在你会看到:

del ghost
after del ghost
gc.collect
callback <weakref at 00B55FC0; dead>
after gc.collect

请注意,默认情况下,此GC已启用并将不时运行。它将清理您的ghost对象,因为它们将成为无法访问的循环引用。

答案 1 :(得分:2)

选项是:

class Ghost(object):
    def __init__(self):
        self.switch = {'eat':Ghost.eat, 'sleep':Ghost.sleep}

所以方法保持不受限制。