fra*_*xel 7 python garbage-collection initialization
我正在编写一个简单的平台游戏,我发现在删除'ghost'实例时,它们会持续存在并且不会被垃圾收集.似乎虽然我删除了所有引用,但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
Run Code Online (Sandbox Code Playgroud)
问题:
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'
Run Code Online (Sandbox Code Playgroud)
印刷:
del ghost
after del ghost
callback <weakref at 00B55FC0; dead>
Run Code Online (Sandbox Code Playgroud)
所以实际的物体只是在关机时被清理了。
您可以手动运行GC看看效果。将其添加到上面脚本的末尾:
print 'gc.collect'
import gc
gc.collect()
print 'after gc.collect'
Run Code Online (Sandbox Code Playgroud)
现在你会看到:
del ghost
after del ghost
gc.collect
callback <weakref at 00B55FC0; dead>
after gc.collect
Run Code Online (Sandbox Code Playgroud)
请注意,默认情况下,此 GC 处于启用状态并且会不时运行。它将清理你的ghost对象,因为它们变成了无法访问的循环引用。