Ho qualche codice in cui le istanze di classi hanno genitore < - riferimenti> bambino gli uni agli altri, per esempio:Come e quando usare in modo appropriato weakref in 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()
ho che questo crea i riferimenti circolari tali che root
, c1
e c2
non saranno liberati dopo che Run() è completato, giusto ?. Quindi, come farli liberare? Penso di poter fare qualcosa come root.children.clear()
o self.parent = None
- ma cosa succede se non so quando farlo?
È un momento appropriato per utilizzare il modulo weakref? Cosa, esattamente, mi indebolisco? l'attributo parent
? L'attributo children
? L'intero oggetto? Tutti i precedenti? Vedo parlare di WeakKeyDictionary e weakref.proxy, ma non mi è chiaro come debbano essere usati, se non del tutto, in questo caso.
Questo è anche su python2.4 (impossibile aggiornare).
Aggiornamento: Esempio di Sintesi
Nei oppone weakref-ify dipende da quale oggetto può vivere senza l'altro, e quali oggetti dipendono l'uno dall'altro. L'oggetto che vive più a lungo dovrebbe contenere oggetti deboli per gli oggetti a vita più breve. Allo stesso modo, le deboli riforme non dovrebbero essere indirizzate alle dipendenze: se lo sono, la dipendenza potrebbe scomparire silenziosamente anche se è ancora necessaria.
Se, per esempio, si ha una struttura ad albero, root
, che ha figli, kids
, ma può esistere senza bambini, allora l'oggetto root
dovrebbe usare weakrefs per la sua kids
. Questo è anche il caso se l'oggetto figlio dipende dall'esistenza dell'oggetto genitore. Di seguito, l'oggetto secondario richiede un genitore per calcolarne la profondità, quindi il riferimento forte per parent
. I membri dell'attributo kids
sono facoltativi, tuttavia, in questo modo vengono utilizzati i criteri deboli per impedire un riferimento circolare.
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.
Per capovolgere il rapporto in giro, abbiamo qualcosa di simile alla seguente. Qui, le classi Facade
richiedono un'istanza Subsystem
per funzionare, quindi utilizzano un riferimento forte al sottosistema di cui hanno bisogno. Subsystem
s, tuttavia, non è necessario un Facade
per funzionare. Subsystem
s fornisce semplicemente un modo per notificare le azioni di ciascuno Facade
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
Inoltre, se sei sicuro di non aver bisogno del gc ciclico, puoi disabilitarlo per un piccolo aumento di prestazioni . –
Grazie, Alex. C'è una ragione specifica per weakref 'children' piuttosto che' parent'? L'effetto sarebbe lo stesso? Cosa accadrebbe se anche il 'genitore 'fosse debole? Nel caso di una lista a doppio collegamento, dovremmo 'prev',' next', o entrambi essere weakrefs? –
Questo è un cattivo suggerimento. Tutti i bambini nell'esempio verranno distrutti subito dopo il ritorno da "Run()". In generale si lega quasi sempre una radice della struttura alla variabile, quindi il modo corretto è usare 'weakref' per' parent', ma non 'children'. –