在Python中删除一个对象及其所有引用?

时间:2012-04-09 03:27:11

标签: python c memory-management swig

有没有办法一次删除对象的所有引用?我知道这是unpythonic,所以我会解释我正在尝试做什么,也许有人知道更好的方法。

我正在围绕一个用于C库的SWIG包装器编写面向对象的包装器。当删除其中一个C对象的代理时,它也会删除子对象(直接在C中)。我想这也会触发在Python中删除他们的代理对象。否则我会遇到这样一种情况:Python对象带有无效指针,如果它们被访问将会出现段错误。

它看起来像这样:

class Parent(object):
    def __init__(self):
        self.ptr = swig.createParent()
    def __del__(self):
        swig.deleteParent(self.ptr) # also deletes children

class Child(object):
    def __init__(self, parent):
        self.ptr = swig.createChild(parent)
    def __del__(self):
        swig.deleteChild(self.ptr)

这就是我担心的情况:

p = Parent()
c = Child(parent)
del p
# accessing c.ptr now would be bad right?

2 个答案:

答案 0 :(得分:3)

如果我理解正确,你将包装一些C代码,并且C代码有一个可以被调用的析构函数。之后,任何使用指向C代码对象的指针都会导致致命的崩溃。

我不确定你的确切情况,所以我会给你两个替代答案。

0)如果C对象由于某种原因而无法控制,并且您需要确保Python包装器代码不会崩溃,则需要让Python包装器知道C对象是否可用或不。使您的Python对象处理指针不再有效。您可以引发Python异常,返回错误代码,或者让方法函数变为无操作函数,具体取决于您正在执行的操作。 C对象消失不会释放Python对象,因此您可以干净利落地处理它。

1)如果仅在释放Python对象时释放C对象,则表示没有问题。 Python引用,当它们超出范围或者在它们上面调用del()时,不会释放Python对象;他们只是减少该对象的引用计数。当引用计数变为零时,然后释放对象,并且您的__del__()方法函数可以调用C代码来释放C对象。

您可以通过运行此代码来了解其工作原理:

class DelTest(object):
    def __init__(self):
        print "__init__() called: object %08x created" % id(self)
    def __del__(self):
        print "__del__() called: object %08x destroyed" % id(self)

print "begin"
print "creating object, binding to name d"
d = DelTest()
print "adding reference bound to name x"
x = d
print "adding reference bound to lst[0]"
lst = []
lst.append(d)
print "deleting lst"
del(lst)
print "deleting x"
del(x)
print "deleting d"
del(d)
print "end"

以上输出:

begin
creating object, binding to name d
__init__() called: object 01e4db50 created
adding reference bound to name x
adding reference bound to lst[0]
deleting lst
deleting x
deleting d
__del__() called: object 01e4db50 destroyed
end

答案 1 :(得分:0)

关于behavior of __del__() method的说明。

  

del x不直接调用x.__del__() - 前者将x的引用计数递减1,而后者仅在x的引用计数达到零时调用。

因此,即使您删除parent,也不一定意味着__del__会立即执行,直到有任何引用为止。这是一个例子。

>>> class C(object):
...     def __del__(self):
...         print "deleting object of type: %s" %self.__class__
... 
>>> class D(object):
...     def __init__(self, parent):
...         self.parent = parent
...     def __del__(self):
...         print "deleting object of type: %s" % self.__class__
... 
>>> c = C()
>>> d = D(c)
>>> del c
>>> del d
deleting object of type: <class '__main__.D'>
deleting object of type: <class '__main__.C'>

请注意,在__del__来电之后,C del d方法称为