3

有没有办法一次删除对对象的所有引用?我知道那是不合情理的,所以我会解释我正在尝试做的事情,也许有人知道更好的方法。

我正在为 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?
4

2 回答 2

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
于 2012-04-09T03:52:29.093 回答
0

关于method行为的__del__()注释。

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

因此,即使您 delete 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调用的。

于 2012-04-09T03:41:33.247 回答