我在Python解释器中提交了以下命令,发现
w.destroy()
小部件的tkinter
方法并没有根除(即消除其存在)tkinter
小部件。
>>> root=tk.Tk()
>>> a = ttk.Button(root, text="Button")
>>> a.grid(row=0, column=0)
>>> a
<tkinter.ttk.Button object .!button>
>>> a.destroy()
>>> a
<tkinter.ttk.Button object .!button>
>>> a.grid(row=0, column=0)
Traceback (most recent call last):
File "/usr/lib/python3.10/idlelib/run.py", line 578, in runcode
exec(code, self.locals)
File "<pyshell#23>", line 1, in <module>
File "/usr/lib/python3.10/tkinter/__init__.py", line 2522, in grid_configure
self.tk.call(
_tkinter.TclError: bad window path name ".!button"
>>> b
Traceback (most recent call last):
File "/usr/lib/python3.10/idlelib/run.py", line 578, in runcode
exec(code, self.locals)
File "<pyshell#24>", line 1, in <module>
NameError: name 'b' is not defined
>>> del a
>>> a
Traceback (most recent call last):
File "/usr/lib/python3.10/idlelib/run.py", line 578, in runcode
exec(code, self.locals)
File "<pyshell#26>", line 1, in <module>
NameError: name 'a' is not defined
>>> root.destroy()
>>> root
<tkinter.Tk object .>
>>> del root
>>> root
Traceback (most recent call last):
File "/usr/lib/python3.10/idlelib/run.py", line 578, in runcode
exec(code, self.locals)
File "<pyshell#30>", line 1, in <module>
NameError: name 'root' is not defined
>>>
引用文档:
w.destroy()
Calling w.destroy() on a widget w destroys w and all its children.
在上面的例子中,虽然
a.destroy()
确实移除了ttk.Button
的外观并且不让a
运行其他tkinter方法,但是a
仍然被识别为<tkinter.ttk.Button object .!button>
对象,即a
的存在
并没有从 Python 解释器中消失。仅在通过 a
命令删除 del a
后,才会在调用 NameError: name 'a' is not defined
时引发 a
异常。在root.destroy()
中可以看到相同的结果。
我认为
tkinter
包维护者需要在其 del w
方法中包含 w
命令(这里,.destroy()
指任何 tkinter 小部件)。如果没有,tkinter 用户目前需要在每个 del w
方法之后运行 w.destroy()
命令,以确保 Python 代码的整洁。我的推理合理吗?
按照我评论中的想法,下面是消除类属性的类方法的示例:
>>> class App(tk.Frame):
def __init__(self, master, **kw):
super().__init__(master, bg="pink")
self.master = master
self.bn = tk.Button(self, text="Button", bg="cyan", width=10, height=2)
self.bn.grid(row=0, column=0)
def eradicate(self):
del self.bn
>>> root = tk.Tk()
>>> root.geometry("150x150+10+10")
''
>>> app = App(root)
>>> app.grid(row=0, column=0)
>>> root.columnconfigure(0, weight=1)
>>> root.rowconfigure(0, weight=1)
>>> app.eradicate()
>>> app.bn
Traceback (most recent call last):
File "/usr/lib/python3.10/idlelib/run.py", line 578, in runcode
exec(code, self.locals)
File "<pyshell#116>", line 1, in <module>
AttributeError: 'App' object has no attribute 'bn'
我认为 tkinter 包维护者需要在其 .destroy() 方法中包含一个 del w 命令(这里,w 指任何 tkinter 小部件)。如果没有,tkinter 用户目前需要在每个 w.destroy() 方法之后运行 del w 命令,以确保其 Python 代码的整洁。我的推理合理吗?
不,你的推理不合理。对象不能销毁引用该对象的变量。例如,一个对象可以被多个变量引用,代码应该如何知道要销毁哪个变量?如果您不希望引用被破坏怎么办?在某些用例中,即使小部件本身已被销毁,您也希望保留引用。
几乎不需要在保存对小部件的引用的变量上调用
del
。当 Python 检测到不再使用这些对象时,它能够自动销毁这些对象(称为垃圾收集器)。