2012-04-09 6 views
2

オブジェクトへのすべての参照を一度に削除する方法はありますか?私はそれが不潔であることを知っているので、私は何をしようとしているのかを説明し、誰かがより良い方法を知っているかもしれない。オブジェクトとそのすべての参照をPythonで削除しますか?

私は、Cライブラリ用のSWIGラッパーの周りにオブジェクト指向のラッパーを作成しています。 Cオブジェクトのいずれかのプロキシが削除されると、(C言語で直接)子オブジェクトも削除されます。 Pythonでプロキシオブジェクトの削除をトリガーすることも欲しいです。さもなければ、私は状況に遭遇します。そこには、アクセスされた場合にsegfaultする無効なポインタを持ち歩く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? 
+1

が重複する可能性を( http://stackoverflow.com/questions/3013304/how-to-delete-every-reference-of-an-object-in-python) – agf

+1

恐らく重複する質問:http://stackoverflow.com/questions/3013304/how -to-delete-in-object-in-pythonの参照 – Pinch

+1

@Duc複製を見つけたらクローズするのに十分な担当者がいない場合は、それをリンクするだけでなく、複製としてフラグを立てることもできます。 – agf

答えて

2

あなたが正しく理解していれば、あなたはいくつかのCコードをラッピングしており、Cコードは呼び出すことができるデストラクタを持っています。その後、Cコードオブジェクトへのポインタを使用しようとすると、致命的なクラッシュが発生します。

あなたの状況はわかりませんので、私はあなたに2つの代替回答を与えるつもりです。

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" 

出力:

あなたはそれがこのコードを実行することにより、どのように機能するかを見ることができます[?Pythonでオブジェクトのすべての参照を削除する方法]の

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 
+0

私のケースでは、私がする必要があるのは、各ChildオブジェクトのParentへの参照を保持することだけです。しかし、これは間違いなく良い解決策です。 – Jeff

0

behavior of __del__() methodに関する注意。

デルXが直接x.__del__()を呼び出しません - 前者デクリメントXの参照カウントがゼロに達したときに一つの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'> 

C__del__方法がdel dコールと呼ばれることに注意してください。

+1

私は、c.ptrがPythonリファレンスではないので、この場合ガベージコレクタが失敗すると考えました。これはSWIGポインタです。だから、pはParentへの唯一の参照でした。しかし、それは私が以前考えなかった明らかな解決策をもたらします。ちょうどChild - > ParentからのPythonリファレンスを保つだけです。 – Jeff

関連する問題