对于笨拙的措辞,我们很抱歉。
目前,我正在使用Tkinter为我的程序创建UI。我在我的Tk窗口中使用了单独的类,一个作为主菜单,一直打开,另一些打开以进行短暂的交互。我希望通过命名它然后通过它的全局名称调用它来让其他函数与我的main函数交互。
经过测试,我最终得到了NameErrors。我把它归结为IDLE中的这个例子:
>>> def test():
mm.do()
>>> class tclass:
def __init__(self):
self.text = "Test text"
test()
def do(self):
print self.text
>>> mm = tclass()
Traceback (most recent call last):
File "<pyshell#16>", line 1, in <module>
mm = tclass()
File "<pyshell#15>", line 4, in __init__
test()
File "<pyshell#8>", line 2, in test
mm.do()
NameError: global name 'mm' is not defined
有没有人有任何建议来规避这个问题?
更新,更多信息:基本上我打算在打开新窗口时禁用窗口按钮,然后在新窗口的某个功能点之后,调用主菜单&#39 ; s重新启用其按钮的功能。在我完成这个项目的过程中,我仍然积极地学习Python,并且还没有意识到我的Tkinter教程使用了旧代码。到目前为止,我还没有必要上课。我现在将转换为新的样式类。
答案 0 :(得分:1)
这不起作用。原因很简单:
mm = tclass()
这相当于以下内容:
temp = tclass()
mm = temp
即,我的观点是首先评估作业的右侧。因此,在您的情况下,创建对象并运行初始化程序。 __init__
调用test
和test
尝试访问对象mm
。它无法在本地命名空间中找到它,因此它会进入全局命名空间,并且仍然没有mm
。所以它失败了。
假设它不会失败,只有然后调用tclass()
返回,并且值(对象实例)可以分配给mm
,在全局创建该名称命名空间。所以只有现在,test
函数才能运行。
但如果之前存在mm
,问题仍然存在。因为在test()
内调用的__init__
将总是访问mm
的旧值,而不是新构造的对象。
相反,您应该不依赖于全局变量,只需将实例传递给函数:
def test(mm): # mm is now a parameter
mm.do()
class tclass:
def __init__(self):
self.text = "Test text"
test(self) # pass the current instance to the function
def do(self):
print self.text
mm = tclass()
答案 1 :(得分:0)
这失败是因为在{Python}完成构建和初始化mm
实例(在tclass
中)之后,mm = tclass()
变量才存在。直到__init__()
返回时才会这样做。您需要将self
明确地作为参数传递给test()
函数,或者不要从test()
调用__init__()
。
您还可以将test()
重写为方法,这样您就可以自动传递self
参数。但在其他情况下这可能效果不佳。如果你需要一个方法和一个函数,考虑写这样的东西:
def test():
return mm.test()
class tclass(object):
# I suggest using a new-style class unless there's a good reason not to
def __init__(self):
self.text = "Test text"
self.test()
def do(self):
print self.text
def test(self):
self.do()
mm = tclass()