Wie und wann man in Python passend einsetzt

Ich habe einen Code, in dem Instanzen von Klassen übergeordnete <-> Kinderreferenzen zueinander haben, zB:

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() 

Ich denke, das schafft kreisförmige Referenzen, so dass root , c1 und c2 nicht befreit werden, nachdem Run () abgeschlossen ist, richtig ?. Also, wie kommen sie zu befreien? Ich glaube, ich kann so etwas wie root.children.clear() oder self.parent = None – aber was, wenn ich nicht weiß, wann das zu tun?

  • Kreisreferenz mit Pythonlisten
  • Ist dies eine passende Zeit, um das schwachwand-Modul zu benutzen? Was genau, schwäche ich? Das parent Attribut? Die children Attribute? Das ganze objekt Alles das oben Genannte? Ich sehe, rede über das WeakKeyDictionary und weakref.proxy, aber es ist mir nicht klar, wie sie verwendet werden sollten, wenn überhaupt, in diesem Fall.

    Dies ist auch auf python2.4 (kann nicht aktualisieren).

    Update: Beispiel und Zusammenfassung

    Welche Gegenstände zu schwach-ify hängt davon ab, welches Objekt ohne das andere leben kann und welche Gegenstände von einander abhängen. Das Objekt, das am längsten lebt, sollte Schwachstellen zu den kürzeren Objekten enthalten. Ebenso sollten Schwachstellen nicht zu Abhängigkeiten gemacht werden – wenn sie sind, könnte die Abhängigkeit stillschweigend verschwinden, obwohl sie noch benötigt wird.

    Wenn du zum Beispiel eine Baumstruktur, eine root hat, die Kinder hat, kids , sondern auch ohne Kinder existieren kann, dann sollte das root Schwachstellen für seine kids . Dies ist auch der Fall, wenn das untergeordnete Objekt von der Existenz des übergeordneten Objekts abhängt. Unten, das untergeordnete Objekt benötigt ein Elternteil, um seine Tiefe zu berechnen, daher die stark-ref für die parent . Die Mitglieder des Kinderattributs sind optional, aber so schwächen werden verwendet, um eine kreisförmige Referenz zu verhindern.

     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. 

    Um die Beziehung zu umgehen, haben wir so etwas wie das unten. Hier benötigen die Facade eine Subsystem Instanz, um zu arbeiten, also verwenden sie ein starkes Ref des Subsystems, das sie benötigen. Subsystem s erfordert jedoch keine Facade zu arbeiten. Subsystem s gibt nur einen Weg, um Facade über die Aktionen des anderen zu informieren.

     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 

  • Problem beim Versuchen, pyside-Objekt zu kopieren
  • Wie finde ich alle Variablen mit identischer ID?
  • Kann nicht mit Postgres & Python "COPY FROM" sein
  • Pandas: Chained Aufträge
  • Wie kopiere ich ein Verzeichnis und seinen Inhalt zu einem vorhandenen Ort mit Python?
  • Warum würde shutil.copy () eine Genehmigungsausnahme erheben, wenn cp nicht?
  • 3 Solutions collect form web for “Wie und wann man in Python passend einsetzt”

    Yep, Schwäche ist hier hervorragend. Speziell statt:

     self.children = {} 

    benutzen:

     self.children = weakref.WeakValueDictionary() 

    Nichts anderes braucht Veränderung in deinem Code. Auf diese Weise, wenn ein Kind keine anderen Unterschiede hat, geht es einfach weg – und auch der Eintritt in die children , die dieses Kind als Wert hat.

    Die Vermeidung von Referenzschleifen ist bei der Implementierung von Caches als Motivation für die Verwendung des weakref . Ref-Loops werden Sie nicht töten, aber sie können am Ende verstopfen Ihre Erinnerung, esp. Wenn einige der Klassen, deren Instanzen in ihnen involviert sind, __del__ definieren, da dies die gc des gc beeinträchtigt, diese Loops aufzulösen.

    Ich schlage vor, child.parent = weakref.proxy(self) . Dies ist eine gute Lösung, um kreisförmige Referenzen zu vermeiden, wenn die Lebensdauer der (externen Verweise auf) parent die Lebensdauer des child abdeckt. Im Gegenteil, verwenden Sie weakref für child (wie Alex vorgeschlagen), wenn die Lebenszeit des child die Lebensdauer der parent . Aber weakref niemals weakref wenn sowohl parent als auch child ohne andere lebendig sein können.

    Hier werden diese Regeln mit Beispielen dargestellt. Verwenden Sie schwaches Elternteil, wenn Sie root in einer Variablen speichern und es umgeben, während Kinder darauf zugegriffen werden:

     def Run(): root, c1, c2 = Node(), Node(), Node() root.AddChild("first", c1) root.AddChild("second", c2) return root # Note that only root refers to c1 and c2 after return, # so this references should be strong 

    Verwenden Sie schwache Kinder, wenn Sie alle an Variablen binden, während root durch sie zugegriffen wird:

     def Run(): root, c1, c2 = Node(), Node(), Node() root.AddChild("first", c1) root.AddChild("second", c2) return c1, c2 

    Aber es wird auch nicht für die folgenden arbeiten:

     def Run(): root, c1, c2 = Node(), Node(), Node() root.AddChild("first", c1) root.AddChild("second", c2) return c1 

    Ich wollte klären, welche Referenzen schwach sein können. Der folgende Ansatz ist allgemein, aber ich verwende den doppelt verknüpften Baum in allen Beispielen.

    Logischer Schritt 1.

    Sie müssen sicherstellen, dass es starke Hinweise gibt, um alle Objekte lebendig zu halten, solange Sie sie brauchen. Es könnte in vielerlei Hinsicht geschehen, zum Beispiel durch:

    • [Direktnamen]: eine benannte Referenz auf jeden Knoten im Baum
    • [Container]: ein Verweis auf einen Container, der alle Knoten speichert
    • [Root + children]: ein Verweis auf den Wurzelknoten und Referenzen von jedem Knoten zu seinen Kindern
    • [Verlässt + parent]: Verweise auf alle Blattknoten und Referenzen von jedem Knoten zu seinem Elternteil

    Logischer Schritt 2.

    Jetzt fügen Sie Referenzen hinzu, um Informationen zu vertreten, falls erforderlich.

    Zum Beispiel, wenn Sie [Container] -Ansatz in Schritt 1 verwendet haben, müssen Sie noch die Kanten darstellen. Eine Kante zwischen den Knoten A und B kann mit einer einzigen Referenz dargestellt werden; Es kann in beide richtungen gehen Wieder gibt es viele Optionen, zum Beispiel:

    • [Kinder]: Referenzen von jedem Knoten zu seinen Kindern
    • [Parent]: eine Referenz von jedem Knoten zu seinem Elternteil
    • [Satz von Sätzen]: ein Satz mit 2-Element-Sätzen; Jedes 2-Element enthält Verweise auf Knoten einer Kante

    Natürlich, wenn du [Schritt + Kinder] in Schritt 1 benutzt hast, sind alle deine Informationen schon vollständig vertreten, also überspringst du diesen Schritt.

    Logischer Schritt 3.

    Jetzt fügen Sie Referenzen hinzu, um die Leistung zu verbessern, falls gewünscht.

    Wenn du zum Beispiel in Schritt 1 den [Container] -Ansatz verwende und [Kinder] in Schritt 2 ankommst, könntest du vielleicht die Geschwindigkeit bestimmter Algorithmen verbessern und Referenzen zwischen jedem Knoten und seinem Elternteil hinzufügen. Solche Informationen sind logisch redundant, da man (zu einem Preis in Leistung) aus vorhandenen Daten ableiten kann.


    Alle Referenzen in Schritt 1 müssen stark sein .

    Alle Referenzen in den Schritten 2 und 3 können schwach oder stark sein . Es gibt keinen Vorteil, starke Referenzen zu verwenden. Es gibt einen Vorteil, schwache Referenzen zu verwenden, bis Sie wissen, dass Zyklen nicht mehr möglich sind. Streng genommen, sobald man weiß, dass Zyklen unmöglich sind, macht es keinen Unterschied, ob man schwache oder starke Referenzen benutzt. Aber um darüber nachzudenken, können Sie auch ausschliesslich schwache Referenzen in den Schritten 2 und 3 verwenden.

    Python ist die beste Programmiersprache der Welt.