来自另一个对象的Python对象实例化 - 它是内存泄漏吗?

时间:2016-05-25 17:20:45

标签: python object memory-leaks

考虑以下小型Python GUI程序,用户可以反复单击按钮在窗口1和窗口2之间循环:

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

问题1:由于每个新类都是从另一个类中实例化的,这是内存泄漏吗?

问题2:这是编写此应用程序的最正确和Pythonic方式吗?

问题3:假设问题1的答案为否,如果我将Window1(self.parent)更改为self.something = Window1(self.parent)该怎么办?现在有一个参考,现在是内存泄漏吗?

1 个答案:

答案 0 :(得分:3)

  

问题1:由于每个新类都是从另一个类中实例化的,这是内存泄漏吗?

没有。而且我认为你在内存泄漏和未使用的对象引用之间存在一些混淆。 @kindall在你的问题评论中很好地解释了它。

了解情况的最佳方法是知道tkinter.TopLevel(..)构造函数是side-effects based.它将在根对象中保存对窗口的引用,以便它知道如何处理各种视窗。 您的类的构造函数也是如此。一旦创建了self.window并且某种程度上root引用了它,它的工作就完成了。此对象的引用也是如此,尽管没有明确说明(请参阅下面的问题3的回答)。

  

问题2:这是编写此应用程序的最正确和Pythonic方式吗?

对象Window1Window2对象的引用未被使用的事实也让我感到困惑。除此之外,我可能还会在对象中存储窗口元素(按钮等)的引用 - 它们可能没有立即使用,但它们可能会在以后使用。

  

问题3:假设对问题1的回答是否定的,如果我做了什么   改变了以下几行:

     

窗口1(self.parent)

     

为:

     

self.something = Window1(self.parent)

     

现在有一个参考,现在是内存泄漏吗?

想想以下几行:

launch_window_2_button.config(command=self.launch_window_2)

为了使该行有效,tkinter必须在某处存储self.launch_window2(以及self)的引用,因此您的self.something根本没有做任何重要的事情。 :)