Question

Je suis en train de stocker des callbacks de méthode, mais se référant à elle gardera l'objet lié en vie, donc je l'ai essayé de garder un weakref à la méthode, mais cela ne semble pas être possible?

  • Pourquoi ne puis-je garder un faible ref. le procédé (voir exemple ci-dessous)

  • Quelle est la meilleure façon de garder ref méthode? quelque chose dans la norme lib? Ou je vais devoir garder la fonction et de l'objet ref. séparer?

exemple:

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?"
Était-ce utile?

La solution

J'ai demandé la même question ici ! Dans ma question, je parle de GObject, mais nous reconnaissons qu'il est un problème général dans tout type de Python! Je suis aide par lioro là, et ce que j'utilise dans mon code actuel est ci-dessous. Quelques points importants:

  • Vous ne pouvez pas weakref l'objet de la méthode. Vous devez weakref l'instance et son attribut de fonction, ou simplement le nom de la méthode (comme je le fais dans mon code ci-dessous)

  • Vous pouvez ajouter un mécanisme pour supprimer le rappel lorsque votre objet connecté va, si vous ne le faites pas, vous aurez l'objet WeakCallback en direct sur place, et exectute une méthode vide lorsque le produit même.

.

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

Notes d'utilisation:

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

J'utilise l'attribut WeakCallback.token dans les sous-classes que j'ai fait pour gérer de déconnecter le rappel lorsque le connecteur disparaît

Autres conseils

Puisque la méthode est lié à l'objet, qu'est-ce que vous vous attendez à voir avec elle si l'objet ne marche pas exister? Que voulez-auto contenir?

Si vous ne avez pas besoin de l'objet dans la méthode, faire un classmethod. Ensuite, votre objet sera GC:. D, même si vous avez une référence normale à la méthode

recette 6.10 livre de recettes Python, "Garder Références aux méthodes Bound Sans Inhibiting Garbage Collection", propose une discussion concise mais assez approfondie et des solutions. Vous pouvez le lire en ligne (sur Google Livres) ici ; nous donnons crédit pour cette recette à Knapka, Jolliton et Nicodemus (partie de la recette de livre de cuisine Activestate originale qu'une autre réponse déjà mentionné) mais bien sûr, comme d'habitude dans le livre de recettes, nous (moi, ma femme Anna, et David Ascher) sont les les responsables du flux global de discussion et de la version du code exact choisi pour l'impression, donc, si quelque chose ne va pas avec ceux-ci, il est notre faute; -).

Ils ont une bonne solution dans:

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

Jetez un oeil au dernier exemple, publié par Anonymous.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top