我想了解对象删除如何在python上运行。这是一组非常简单的代码。
class A(object):
def __init__(self):
setattr(self, "test", self._test)
def _test(self):
print "Hello, World!"
def __del__(self):
print "I'm dying!"
class B(object):
def test(self):
print "Hello, World!"
def __del__(self):
print "I'm dying"
print "----------Test on A"
A().test()
print "----------Test on B"
B().test()
Pythonista会认识到我正在运行python 2.x版本。更具体地说,此代码在python 2.7.1安装程序上运行。
此代码输出以下内容:
----------Test on A
Hello, World!
----------Test on B
Hello, World!
I'm dying
令人惊讶的是,A
对象未被删除。我可以理解为什么,因为setattr
中的__init__
语句产生循环引用。但这个似乎很容易解决。
最后,这个页面在python documentation (Supporting Cyclic Garbage Collection)中表明可以处理这种循环引用。
我想知道:
__del__
课程中的A
方法?object
子类不支持循环垃圾收集?setattr
,如何处理这种__del__
?注意:在A
setattr
如果{{1}}指向我模块的其他方法,则没有问题。
答案 0 :(得分:1)
实例方法通常存储在类中。解释器首先在实例__dict__
中查找它们,它失败了,然后查看成功的类。
在A
中动态设置__init__
的实例方法时,可以在实例字典中创建对它的引用。此引用是循环的,因此引用计数器永远不会为零,并且引用计数器不会清除A
。
>>> class A(object):
... def _test(self): pass
... def __init__(self):
... self.test = self._test
...
>>> a = A()
>>> a.__dict__['test'].im_self
垃圾收集器是Python用来处理循环引用的东西。不幸的是,它无法使用__del__
方法处理对象,因为通常它无法确定调用它们的安全顺序。相反,它只是将所有这些对象放在gc.garbage
中。然后你可以去那里打破周期,这样他们就可以被释放。来自docs
gc.garbage
收集器发现无法访问但可能无法访问的对象列表 不被释放(无法收集的物品)。默认情况下,此列表仅包含 具有
__del__()
方法的对象。具有__del__()
方法的对象 并且是参考循环的一部分导致整个参考循环 无法收集,包括不一定的对象 在循环中但只能从它到达。 Python不收集这样的 自动循环,因为一般来说,Python不可能 猜测运行__del__()
方法的安全顺序。如果你 知道一个安全的命令,你可以通过检查垃圾来强制解决问题 列表,并明确地打破由于您的对象内的周期 名单。请注意,这些物体即使如此也能保持活力 在垃圾清单中,所以它们也应该从垃圾中删除。 例如,在打破周期后,执行del gc.garbage[:]
清空 名单。通过不创建周期来避免这个问题通常会更好 包含__del__()
方法的对象,可以检查garbage
在这种情况下,要验证没有创建这样的周期。
如果您希望对象进行垃圾回收,请不要使用__del__
方法对对象进行循环引用。
答案 1 :(得分:0)
您应该仔细阅读documentation on the __del__
方法 - 具体而言,使用__del__
方法的对象改变收集器工作方式的部分。
gc module提供了一些钩子,您可以自己清理它。
我怀疑根本没有__del__
方法会导致您的对象被正确清理。您可以查看gc.garbage
并查看您的A
实例是否存在来验证这一点。