tengo algo de código en la que las instancias de clases tienen padres < - referencias> niño entre sí, por ejemplo:¿Cómo y cuándo utilizar adecuadamente weakref en Python
class Node(object):
def __init__(self):
self.parent = None
self.children = {}
def AddChild(self, name, child):
child.parent = self
self.children[name] = child
def Run():
root, c1, c2 = Node(), Node(), Node()
root.AddChild("first", c1)
root.AddChild("second", c2)
Run()
I que esto crea referencias circulares de tal manera que root
, c1
y c2
no se liberarán después de que se complete Run(), ¿verdad ?. Entonces, ¿cómo lograr que sean liberados? Creo que puedo hacer algo como root.children.clear()
o self.parent = None
, pero ¿y si no sé cuándo hacerlo?
¿Es este el momento apropiado para usar el módulo weakref? ¿Qué, exactamente, defiendo débilmente? el atributo parent
? El atributo children
? El objeto completo? Todas las anteriores? Veo hablar sobre WeakKeyDictionary y weakref.proxy, pero no tengo claro cómo deberían usarse, si es que lo hacen, en este caso.
Esto también está en python2.4 (no se puede actualizar).
Actualización: Ejemplo y resumen
Lo que se opone a weakref-ify depende de qué objeto se puede vivir sin el otro, y qué objetos dependen unos de otros. El objeto que vive más tiempo debe contener elementos débiles para los objetos de vida más corta. Del mismo modo, las revisiones débiles no deberían hacerse a las dependencias; si lo son, la dependencia podría desaparecer silenciosamente aunque todavía se necesite.
Si, por ejemplo, que tienen una estructura de árbol, root
, que tiene hijos, kids
, pero puede existir sin hijos, entonces el objeto root
debe utilizar weakrefs por su kids
. Este es también el caso si el objeto secundario depende de la existencia del objeto principal. A continuación, el objeto secundario requiere un padre para calcular su profundidad, de ahí la referencia fuerte para parent
. Sin embargo, los miembros del atributo kids
son opcionales, por lo que las referencias débiles se utilizan para evitar una referencia circular.
class Node:
def __init__(self)
self.parent = None
self.kids = weakref.WeakValueDictionary()
def GetDepth(self):
root, depth = self, 0
while root:
depth += 1
root = root.parent
return depth
root = Node()
root.kids["one"] = Node()
root.kids["two"] = Node()
# do what you will with root or sub-trees of it.
Para darle la vuelta a la relación, tenemos algo como lo que se muestra a continuación. Aquí, las clases Facade
requieren una instancia Subsystem
para funcionar, por lo que usan una referencia fuerte para el subsistema que necesitan. Subsystem
s, sin embargo, no requieren un Facade
para funcionar. Subsystem
s solo proporciona una forma de notificar Facade
s acerca de las acciones de los demás.
class Facade:
def __init__(self, subsystem)
self.subsystem = subsystem
subsystem.Register(self)
class Subsystem:
def __init__(self):
self.notify = []
def Register(self, who):
self.notify.append(weakref.proxy(who))
sub = Subsystem()
f1 = CliFacade(sub)
f2 = WebFacade(sub)
# Go on to reading from POST, stdin, etc
Además, si está seguro de que no necesitará el gc cíclico, puede desactivarlo para un pequeño aumento del rendimiento . –
Gracias, Alex. ¿Hay alguna razón específica para rechazar los "niños" en lugar de "padres"? ¿El efecto sería el mismo? ¿Qué pasaría si 'parent 'fuera débil también? En el caso de una lista de doble enlace, ¿deberían 'prev ',' next', o ambos ser weakrefs? –
Esta es una mala sugerencia. Todos los niños del ejemplo serán destruidos justo después de regresar de 'Ejecutar()'. En general, casi siempre vincula una raíz de estructura a variable, por lo que la forma correcta es usar 'weakref' para' parent', pero no 'children'. –