2016-05-25 5 views
0

Betrachten Sie das folgende kleine Python GUI-Programm, in dem der Benutzer eine Taste über und über, um zwischen Fenster 2 1 und Fenster klicken:Python-Objekt Instanziierung aus einem anderen Objekt - ist es ein Speicherleck?

import tkinter 

class Window1: 
    def __init__(self, parent): 
     # Initialize a new GUI window 
     self.parent = parent 
     self.window = tkinter.Toplevel(self.parent) 
     self.window.title('Window 1') 

     # Make a button to launch Window 2 
     launch_window_2_button = tkinter.Button(self.window, text='Launch Window 2') 
     launch_window_2_button.config(command=self.launch_window_2) 
     launch_window_2_button.pack() 

    def launch_window_2(self): 
     self.window.destroy() 
     Window2(self.parent) 


class Window2: 
    def __init__(self, parent): 
     # Initialize a new GUI window 
     self.parent = parent 
     self.window = tkinter.Toplevel(self.parent) 
     self.window.title('Window 2') 

     # Make a button to launch Window 1 
     launch_window_1_button = tkinter.Button(self.window, text='Launch Window 1') 
     launch_window_1_button.config(command=self.launch_window_1) 
     launch_window_1_button.pack() 

    def launch_window_1(self): 
     self.window.destroy() 
     Window1(self.parent) 


if __name__ == "__main__": 
    # Initialize and hide the root GUI 
    # (each class will spawn a new window that is a child of the root GUI) 
    root = tkinter.Tk() 
    root.withdraw() 
    Window1(root) # Start by spawning Window 1 
    root.mainloop() 

Frage 1: Da jede neue Klasse von innen instanziiert wird eine andere Klasse, ist das ein Speicherleck?

Frage 2: Ist dies die korrekte und pythonische Art, diese Anwendung zu programmieren?

Frage 3: Unter der Annahme, dass die Antwort auf Frage 1 ist nicht, was passiert, wenn ich Window1(self.parent)-self.something = Window1(self.parent) geändert. Jetzt wo es eine Referenz gibt, ist es jetzt ein Speicherleck?

+3

Ein Speicherverlust ist, wenn Sie Speicher nicht freigeben, wenn es nicht mehr verwendet wird. Wenn Sie beispielsweise über ein Programm verfügen, das Zeilen aus einer Datei liest und für jede Zeile neuen Speicher reserviert, den Speicher einer Zeile jedoch nie freigibt, bevor Sie die nächste Zeile lesen, handelt es sich um ein Speicherleck. Es gibt keine Möglichkeit, diesen Speicher freizugeben, da Sie keinen Verweis mehr darauf haben, so dass die von Ihrem Programm verwendete Speichermenge wächst und wächst. Python verwaltet den Speicher für Sie, und in diesem Szenario würde der Speicher automatisch freigegeben werden. Wie oder wo ein Objekt instanziiert wird, hat damit nichts zu tun. – kindall

Antwort

3

Frage 1: Da jede neue Klasse aus einer anderen Klasse instanziiert wird, ist das ein Speicherleck?

Nein. Und ich denke, Sie sind verwirrt zwischen ein paar Sachen Speicherleck und Objektreferenzen nicht verwendet werden. @kindall erklärt es schön in seinem Kommentar unter deiner Frage.

Der beste Weg, um zu verstehen, was los ist, zu wissen, dass der tkinter.TopLevel(..) Konstruktor ist side-effects based. Es wird die Referenz auf das Fenster innerhalb des Root-Objekts halten, so dass sie weiß, wie man mit verschiedenen Fenstern beschäftigen. Und so ist der Konstruktor Ihrer Klasse. Sobald es eine self.window erstellt und irgendwie root Bezug hat, ist seine Arbeit erledigt. Die Referenz zu diesem Objekt wird ebenfalls nicht explizit angegeben (siehe Antwort auf Ihre Frage 3).


Frage 2: Ist dies der richtige und Pythonic Weg, um diese Anwendung zu codieren?

Die Tatsache, dass Verweise auf die Objekte Window1 und Window2 Objekte nervt mich auch nicht verwendet. Ansonsten würde ich wahrscheinlich die Referenzen der Fensterelemente (Buttons, etc.) auch innerhalb des Objekts speichern - Sie könnten nicht sofort verwendet werden, aber sie könnten später sein.


Frage 3: Unter der Annahme, dass die Antwort auf Frage 1 ist nicht, was passiert, wenn ich die folgenden Zeilen geändert:

Window1 (self.parent)

zu:

self.something = Window1 (self.parent)

Jetzt, wo es eine Referenz gibt, ist es ein Speicher lea kennt?

Denken Sie über die unten Linie:

launch_window_2_button.config(command=self.launch_window_2) 

Um diese Linie zu arbeiten, tkinter die Referenz von self.launch_window2 speichern muss (und damit self) irgendwo, so dass Ihre self.something nichts tun signifikant überhaupt .. :)

+0

Vielen Dank! Können Sie mir ein Code-Snippet zeigen, das "Die Tatsache anspricht, dass Verweise auf die Objekte Window1 und Window2 nicht verwendet werden"? Ich verstehe das nicht ganz. Warum sollte ich im Zusammenhang mit diesem Programm einen Verweis auf diese Fenster haben? – James

+0

Im Kontext dieses Programms möchten Sie möglicherweise die Verweise auf das Window-Objekt nicht. Ich habe nur angedeutet, wie sehr es mich stört, keinen zu haben. Persönlich mag ich nicht die Idee einer tief verschachtelten Funktion, die die Referenz eines Objekts speichert. Es * deutet * wahrscheinlich auf einen schlechten "Besitz" von Ressourcen hin. Aber da dies eine Bibliothek ist, glaube ich nicht, dass du viel dagegen tun kannst ... leider – SuperSaiyan

Verwandte Themen