有没有办法一次删除对象的所有引用?我知道这是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?
答案 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
方法称为。