2

私はいくつかのメソッドコールバックを保存しようとしていますが、それを参照するとバインドされたオブジェクトが存続するので、メソッドへのweakrefを保持しようとしましたが、それは不可能のようですか?

それで

  • なぜ私は弱い参照を維持できないのですか?メソッドへ(以下の例を参照)

  • メソッドrefを保持するための最良の方法は何ですか?標準ライブラリに何かありますか?または、関数とオブジェクトの参照を保持する必要があります。分ける?

例:

import weakref

class A(object):
    def m(self): pass

a = A()

import weakref

class A(object):
    def m(self): pass

a = A()

rm = weakref.ref(a.m)
print "is weak ref to method dead?",rm() is None
print "Q1. why can't i keep weakref to bound method?"

ra = weakref.ref(a)
m = a.m
print "delete object"
del a
print "is object dead?",ra() is None
print "delete method"
del m
print "is object dead?",ra() is None
print "Q2. hmmm so i am stuck i can't keep a ref as it stops the object from gc, but weakref to method isn't working?"
4

4 に答える 4

3

メソッドはオブジェクトにバインドされているので、オブジェクトが存在しない場合、メソッドをどのように処理することを期待しますか?自己完結するものは何ですか?

メソッドにオブジェクトが必要ない場合は、クラスメソッドにします。その場合、メソッドへの通常の参照がある場合でも、オブジェクトはGC:dになります。

于 2009-11-04T12:35:02.240 に答える
2

Pythonクックブックのレシピ6.10、「ガベージコレクションを阻害することなくバインドされたメソッドへの参照を維持する」は、簡潔でありながら非常に徹底的な議論と解決策を提供します。ここでオンライン(Googleブックス)で読むことができます; そのレシピの功績は、Knapka、Jolliton、Nicodemus(一部は別の回答ですでに述べた元のアクティブステートクックブックレシピから)に与えられますが、もちろん、クックブックではいつものように、私たち(私、妻のアンナ、デビッドアッシャー)は議論の全体的な流れと印刷用に選択された正確なコードバージョンに責任があるので、それらに何か問題がある場合、それは私たちのせいです;-)。

于 2009-11-04T15:52:07.703 に答える
0

私はここで同じ質問をしました!私の質問では、GObjectについて話しますが、それはあらゆる種類のPythonの一般的な問題であることを認識しています。そこでlioroの助けを借りました。現在のコードで使用しているものは、以下のとおりです。いくつかの重要なポイント:

  • メソッドオブジェクトをweakrefすることはできません。インスタンスとその関数属性、または単にメソッド名をweakrefする必要があります(以下のコードで行うように)

  • 接続されたオブジェクトがなくなったときにコールバックの登録を解除するメカニズムを追加できます。これを行わないと、代わりにWeakCallbackオブジェクトが有効になり、偶数が発生したときに空のメソッドが実行されます。

class WeakCallback (object):
    """A Weak Callback object that will keep a reference to
    the connecting object with weakref semantics.

    This allows object A to pass a callback method to object S,
    without object S keeping A alive.
    """
    def __init__(self, mcallback):
        """Create a new Weak Callback calling the method @mcallback"""
        obj = mcallback.im_self
        attr = mcallback.im_func.__name__
        self.wref = weakref.ref(obj, self.object_deleted)
        self.callback_attr = attr
        self.token = None

    def __call__(self, *args, **kwargs):
        obj = self.wref()
        if obj:
            attr = getattr(obj, self.callback_attr)
            attr(*args, **kwargs)
        else:
            self.default_callback(*args, **kwargs)

    def default_callback(self, *args, **kwargs):
        """Called instead of callback when expired"""
        pass

    def object_deleted(self, wref):
        """Called when callback expires"""
        pass

使用上の注意:

# illustration how I typically use it
weak_call = WeakCallback(self._something_changed)
long_lived_object.connect("on_change", weak_call)

WeakCallback.tokenコネクタがなくなったときにコールバックの切断を管理するために作成したサブクラスの属性を使用します

于 2009-11-04T13:55:23.927 に答える
0

彼らは次のような素晴らしい解決策を持っています:

http://code.activestate.com/recipes/81253/

Anonymousによって投稿された最後の例を見てください。

于 2009-11-04T14:22:59.463 に答える