У меня есть код, в котором экземпляры классов имеют родительский ↔ дочерний элемент ссылки друг на друга, например:
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()
Я думаю, что это создает круговые ссылки, так что root, c1 и c2 не будут освобождены после завершения Run(), правильно?. Итак, как их освободить? Я думаю, что могу сделать что-то вроде root.children.clear() или self.parent = None - но что, если я не знаю, когда это сделать?
Это подходящее время для использования модуля weakref? Что именно, я слабо понимаю? атрибут parent? Атрибут children? Весь объект? Все вышеперечисленное? Я вижу разговоры о WeakKeyDictionary и weakref.proxy, но неясно, как их следует использовать, если это вообще возможно.
Это также на python2.4 (невозможно обновить).
Обновление: пример и сводка
Какие объекты для weakref-ify зависят от того, какой объект может жить без другого, а какие объекты зависят друг от друга. Объект, который живет дольше всех, должен содержать слабые ссылки на объекты с более коротким периодом. Аналогичным образом, слабые стороны не должны быть связаны с зависимостями - если они есть, зависимость может исчезнуть молча, даже если она по-прежнему необходима.
Если, например, у вас есть древовидная структура, root, у которой есть дети, kids, но может существовать без детей, тогда объект root должен использовать weakrefs для своего kids. Это также имеет место, если дочерний объект зависит от существования родительского объекта. Ниже для дочернего объекта требуется родительский элемент, чтобы вычислить его глубину, и, следовательно, strong-ref для parent. Элементы атрибута kids необязательны, поэтому для предотвращения циклической ссылки используются слабые ссылки.
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.
Чтобы перевернуть отношения вокруг, у нас есть что-то вроде ниже. Здесь для классов Facade требуется, чтобы экземпляр Subsystem работал, поэтому они используют сильную ссылку на подсистему, в которой они нуждаются. Subsystem s, однако, не требует работы Facade. Subsystem просто укажите способ уведомления Facade о действиях друг друга.
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