Duplicar posible:
Why doesn't the weakref work on this bound method?¿Puedo usar métodos de referencia débiles?
Un poco de contexto:
yo estaba tratando de implementar un oyente (o Observador, la misma cosa) patrón: Un EventManager mantiene una lista de todos los manejadores de Oyentes interesados en un Evento. Por ejemplo, un objeto Listener tendría un método onEndOfTheWorldEvent
que sería llamado por el EventManager cada vez que se publicara una instancia de la clase de evento EndOfTheWorldEvent. Fácil.
Excepto que quería hacer una referencia débil a los controladores porque no quiero que el EventManager mantenga mis manejadores (métodos encuadernados) vivos cuando el Listener ya no se necesite.
Así que pensé "Vamos a lanzar todos los controladores en un WeakSet". No pude hacer que funcione.
Introduzco aquí el código (o lo que queda de él cuando lo reduzco al mínimo, aquí solo hay un tipo de evento y solo un tipo de controlador).
#! /usr/bin/python
"""
"""
import sys
import weakref
class Listener(object):
def handler(self, event):
print event
class EventManager(object):
def __init__(self):
self.handlers = weakref.WeakSet()
def register(self, listener):
print "Registering..."
self.handlers.add(listener.handler)
CountRefs(listener.handler)
print "Number of handlers registered:", len(self.handlers)
print "Registered."
def CountRefs(what):
print "Hard count:", sys.getrefcount(what)
print "Weak count:", weakref.getweakrefcount(what)
listener = Listener()
em = EventManager()
CountRefs(listener.handler)
em.register(listener)
CountRefs(listener.handler)
resultado:
Hard count: 3
Weak count: 0
Registering...
Hard count: 3
Weak count: 0
Number of handlers registered: 0
Registered.
Hard count: 3
Weak count: 0
Sólo se ve como nunca hay ninguna referencia débil, y el conjunto queda vacía.
para que sea aún más sencillo:
>>> class C(object):
>>> def blah(self):
>>> print "blah"
>>>
>>> c = C()
>>> w = weakref.ref(c.blah)
>>> print w
<weakref at 0x11e59f0; dead>
no puedo crear weakrefs a métodos en absoluto? Si no, ¿por qué no?
Así que supongo que una solución sería reemplazar el WeakSet con un WeakKeyDictionary: la clave es el oyente en sí mismo, y valora el controlador. De hecho, puedo debilitar a mis oyentes. Pero hace que la estructura de datos sea un poco más complicada, y cuando llega el momento de transmitir los eventos a todo el mundo, hay un nivel más en esa estructura para atravesar.
¿Qué opinas?
Esta pregunta se hace no realmente duplicado, porque se enfoca en una solución y no solo en "por qué no". Dejen solo la buena respuesta aceptada aquí. En el mejor de los casos, puede marcar la otra pregunta como duplicada en el sentido de: "ésta implica la respuesta para el otro". – kxr