我正在写一个简单的平台游戏,我发现在删除“幽灵”游戏时实例,它们坚持并且不是垃圾收集。似乎虽然我删除了所有引用,但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
问题:
答案 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}
所以方法保持不受限制。