Python 内存管理和Tkinter

Python 内存管理和Tkinter,python,memory-management,tkinter,Python,Memory Management,Tkinter,我有一个关于Python中内存管理的问题,特别是关于使用Tkinter的程序。首先,我将从一个示例开始,该示例是我为测试一些简单的内存管理而创建的: import tkinter as tk from tkinter import ttk class Frame1(tk.Frame): def __init__(self, parent, *args, **kwargs): tk.Frame.__init__(self, parent, *args, **kwargs

我有一个关于Python中内存管理的问题,特别是关于使用Tkinter的程序。首先,我将从一个示例开始,该示例是我为测试一些简单的内存管理而创建的:

import tkinter as tk
from tkinter import ttk

class Frame1(tk.Frame):

    def __init__(self, parent, *args, **kwargs):
        tk.Frame.__init__(self, parent, *args, **kwargs)
        self.parent = parent
        self.pack()
        print("Frame1 created")
        btn = ttk.Button(self, text = "PRESS", command = self.openFrame2)
        btn.pack()

    def __del__(self):
        print("Frame1 destroyed")

    def openFrame2(self):
        self.pack_forget()
        self.destroy()
        frame2 = Frame2(self.parent)

class Frame2(tk.Frame):

    def __init__(self, parent, *args, **kwargs):
        tk.Frame.__init__(self, parent, *args, **kwargs)
        self.parent = parent
        self.pack()
        print("Frame2 created")
        btn = ttk.Button(self, text = "CLICK", command = self.openFrame1)
        btn.pack()

    def __del__(self):
        print("Frame2 destroyed")

    def openFrame1(self):
        self.pack_forget
        self.destroy()
        frame1 = Frame1(self.parent)

root = tk.Tk()
program = Frame1(root)
root.mainloop()
这个计划的目标很简单。创建包含带有按钮的框架的Tkinter窗口。当按下该按钮时,删除该帧,释放该帧使用的内容占用的所有内存,并创建一个不同的帧

如果我按
press->CLICK->press
的顺序按下按钮,我的预期结果是:

Frame1已创建
新闻界:
框架1已销毁
框架2已创建
点击:
框架2已销毁
框架1已创建
新闻界:
框架1已销毁
框架2已创建
相反,我的实际结果是:

Frame1已创建
新闻界:
框架2已创建
点击:
框架1已创建
框架2已销毁
新闻界:
框架2已创建
框架1已销毁

我在这里有点困惑<当我调用
self.destroy()
时,code>Frame2似乎正确地调用了
\uu del\uu
方法,但是
Frame1
没有。这是为什么?

您可能需要更改代码中的一些内容

首先回答您在评论中提出的问题:

更好的选择是创建一个手动destroyMe方法,该方法可以检查并删除对象手动使用的所有内容吗

我们不需要使用
pack.forget()
,因为您正在破坏帧

使用容器上的
.destroy()
方法销毁该容器中的所有内容。没有必要一次一个地毁掉一切。您可以在包含多个框架的框架上使用它,这些框架具有自己的一组小部件,它将破坏主框架内所有框架中的所有内容。或者,如果需要,您可以只针对单个小部件

第二,我们不需要
\uu del\uu
。相反,只需将print语句移动到
self.destroy()命令之后即可

看看下面的代码。它将按您在问题上发布的预期顺序打印,同时在过程中销毁自身

import tkinter as tk
from tkinter import ttk


class Frame1(tk.Frame):

    def __init__(self, parent, *args, **kwargs):
        tk.Frame.__init__(self, parent, *args, **kwargs)
        self.parent = parent
        self.pack()
        print("Frame1 created")
        btn = ttk.Button(self, text = "PRESS", command = self.openFrame2)
        btn.pack()

    def openFrame2(self):
        self.destroy()
        print("Frame1 destroyed")
        frame2 = Frame2(root)


class Frame2(tk.Frame):

    def __init__(self, parent, *args, **kwargs):
        tk.Frame.__init__(self, parent, *args, **kwargs)
        self.parent = parent
        self.pack()
        print("Frame2 created")
        btn = ttk.Button(self, text = "CLICK", command = self.openFrame1)
        btn.pack()

    def openFrame1(self):
        self.destroy()
        print("Frame2 destroyed")
        frame1 = Frame1(root)


root = tk.Tk()
frame1 = Frame1(root)
root.mainloop()

Python不能保证何时(或者甚至)是否将调用C++ >代码> >代码>,而不是C++。最好忘记用它来做这件事。相反,请考虑在派生类中重载
destroy()
。FWIW:这不起任何作用:
self.pack\u forget
。即使你正确地调用它(<代码> So.PoCyC遗忘()),因为你在删除之后立即删除了这个小部件。你看,这就是我困惑的地方,因为我是新的Iyto Python,但是知道C++。更好的选择是创建一个手动
destroyMe
方法,该方法将检查并删除对象手动使用的所有内容吗?首先,在对象的所有引用都消失之前,不会调用
\uu del\uuu
(垃圾收集器在运行时调用)。很可能
tkinter
有一些内部引用阻止内存被释放。在
openFrameX()
方法中,为什么要将调用
FrameX(self.parent)
的结果赋给局部变量(函数返回时会立即丢弃)?它不会导致程序出现明显的错误行为,只是浪费cpu周期,因为它无法完成任何任务。由于
.destroy()
可能会从多个位置调用,因此我认为最好在派生类中重载它,并将调用放到
print()
那里。@martineau它只是原始代码的一部分。我甚至没有看那个,因为我没有遇到任何错误。我想我可以修改代码来删除对象而不是框架。(固定类型)
.desrtoy()
将清除框架内的所有内容。这是否包括类中使用的任何对象。如果在
Frame2
类中我创建了say
self.foo=Bar()
,我是否应该在
self.destroy()
之前调用
del self.foo
,以确保删除
self.foo
对象?继承的
.destroy()
对其他类属性一无所知,但它将“知道”关于与
tkinter.Frame
关联的任何小部件。对象