Python - 全局变量和 class 方法
Python - Global variables and class methods
好的,所以我对这个几乎失去了理智。
我正在开发一个小应用程序,它从输入 XML 文件中获取问题,将它们显示在屏幕上,获取答案并将其写回输出 XML,使用 tkinter XML 处理的 GUI 和 ElementTree。
每个问题可能有多个检查和子问题,它们会根据需要动态显示在各自的框架上。
主要 window 由 main
创建为 MainWindow
class 实例(包含所有 tkinter 内容和一堆有用的方法),在代码的最后:
def main():
global app
window = Tk()
app = MainWindow(window)
window.mainloop()
if __name__ == '__main__':
main()
这应该使 'app' 成为一个全局的,应该可以从代码的任何地方访问,对吗?
.....好像不是?
我创建了问题 class,它存储从 XML 中提取的属性,处理文本的显示并为 class 中的每个元素创建检查 class =103=],以及 XML.
中每个元素的子问题 class
题目class如下:
class Question:
def __init__(self, element):
self.element = element
self.question_text = element.get('text')
self.ok = element.get('ok')
self.answer = element.get('r')
self.comment = element.get('comment')
if element.find('check') is None:
#print(app)
pass
else:
#print(app)
for check in element.iter('check'):
Check(check)
for subq in element.iter('subquest'):
SubQuestion(subq)
还有 Check class,它处理复选框的创建以及将它们各自的答案写入 ElementTree:
class Check:
def __init__(self, element):
self.element = element
self.check_text = element.get('text')
self.answer = element.get('r')
self.var = IntVar()
self.create_check()
def create_check(self):
print('check created')
print(app)
Checkbutton(app.frameChk, text=self.check_text, variable=self.var, command=self.write_check).pack(side=LEFT)
def write_check(self):
self.element.set('r', self.var.get())
print('check written')
到目前为止,还不错。它按预期工作,出现了复选框并提交了它们的值,没有问题
但是...您在创建复选框时是否注意到 Check class 引用 app.frameChk
中的 create_check
方法?这是为复选框保留的 Tk 框架,由 MainWindow 的 __init__
方法创建。这个 create_check
方法访问 app
没有任何问题,即使其中没有 global
关键字。我什至添加了 print(app)
只是为了确定。
果然,每次创建复选框时,它都会将 <__main__.MainWindow object at 0x0000024CCC557BE0>"
打印到控制台。
但是...在问题的 __init__
方法(或其他任何地方)中,我似乎无法访问与 app
相关的任何内容,它会抛出 classes_app.py", line 129, in __init__ - print(app) NameError: name 'app' is not defined
到底为什么?这两个 classes 没有从其他人那里继承任何东西,并且在层次上是 'equals',只是程序中的两个平均 classes(实际上,Question 是创建 Check 实例的那个!) .一个人认识全球而其他人不认识?
最令人难以置信的是:Check
class 中没有 global
关键字,它仍然有效?
到目前为止我已经尝试过:
1 - 在全局范围内的 main
函数之外声明 app = MainWindow(window)
。没有。
2 - 在程序的每个函数中使用 global
关键字来查看他们是否得到它。没有。
3 - 将 main
函数放在代码的最顶部,这样它就是第一个
app
的声明似乎也没什么作用。
4 - 上述解决方案和反复试验恶作剧的任意组合。
5 - 牺牲一块主板给python globals 的代码女神。
请注意,我是 python 的新手,所以我可能对全局变量的理解非常错误,或者完全不理解,但根据文档所说,用 global
关键字应该是一个全局变量,并且可以从代码中的所有函数和方法访问全局变量,对吗?
如果你问为什么我如此需要它来让 app = MainWindow(window)
成为全局的:会有一个全局函数来清理每个问题之间的小部件:
def destroy_widgets(parent):
for widget in parent.winfo_children():
widget.destroy()
所以在 classes 的方法中,我会像 destroy_widgets(app.frameChk)
那样称呼它。这是我第一次遇到这个问题。
我会 post 整个代码,但是所有这些 tkinter 定义都非常广泛。如果你们认为有必要,我当然会。
任何帮助或见解将不胜感激,在此先感谢,这个社区是黄金!
Definition/lifetime 个变量
关于这个:
Most mind-boggling: the Check class does NOT have the global keyword in it, and it still works?
您只需要 global
关键字来在本地上下文中创建或更改全局变量,see this answer。
此外,语句 global app
尚未创建变量 app
- 它仅在第一次赋值时创建。在您的示例中,这意味着 app
仅在此处创建:app = MainWindow(window)
。
如果 Question
在此语句之前创建(在您的示例中,通过 Tk()
或 MainWindow(window)
),则 app
尚不存在。
你可以在解释器中试试这个:
>>> global app
>>> print(app)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'app' is not defined
命名空间
另一个需要注意的重要事实:如果您的代码组织在不同的模块中,您必须注意命名空间。
例子
假设我们有两个 python 文件:first.py
和 second.py
:
first.py
的内容:
app = 5
second.py
的内容:
import first
print(first.app)
运行 这个有效:
$ python3 second.py
5
只放 print(app)
是行不通的,因为模块不同。
好的,所以我对这个几乎失去了理智。
我正在开发一个小应用程序,它从输入 XML 文件中获取问题,将它们显示在屏幕上,获取答案并将其写回输出 XML,使用 tkinter XML 处理的 GUI 和 ElementTree。 每个问题可能有多个检查和子问题,它们会根据需要动态显示在各自的框架上。
主要 window 由 main
创建为 MainWindow
class 实例(包含所有 tkinter 内容和一堆有用的方法),在代码的最后:
def main():
global app
window = Tk()
app = MainWindow(window)
window.mainloop()
if __name__ == '__main__':
main()
这应该使 'app' 成为一个全局的,应该可以从代码的任何地方访问,对吗?
.....好像不是?
我创建了问题 class,它存储从 XML 中提取的属性,处理文本的显示并为 class 中的每个元素创建检查 class =103=],以及 XML.
中每个元素的子问题 class题目class如下:
class Question:
def __init__(self, element):
self.element = element
self.question_text = element.get('text')
self.ok = element.get('ok')
self.answer = element.get('r')
self.comment = element.get('comment')
if element.find('check') is None:
#print(app)
pass
else:
#print(app)
for check in element.iter('check'):
Check(check)
for subq in element.iter('subquest'):
SubQuestion(subq)
还有 Check class,它处理复选框的创建以及将它们各自的答案写入 ElementTree:
class Check:
def __init__(self, element):
self.element = element
self.check_text = element.get('text')
self.answer = element.get('r')
self.var = IntVar()
self.create_check()
def create_check(self):
print('check created')
print(app)
Checkbutton(app.frameChk, text=self.check_text, variable=self.var, command=self.write_check).pack(side=LEFT)
def write_check(self):
self.element.set('r', self.var.get())
print('check written')
到目前为止,还不错。它按预期工作,出现了复选框并提交了它们的值,没有问题
但是...您在创建复选框时是否注意到 Check class 引用 app.frameChk
中的 create_check
方法?这是为复选框保留的 Tk 框架,由 MainWindow 的 __init__
方法创建。这个 create_check
方法访问 app
没有任何问题,即使其中没有 global
关键字。我什至添加了 print(app)
只是为了确定。
果然,每次创建复选框时,它都会将 <__main__.MainWindow object at 0x0000024CCC557BE0>"
打印到控制台。
但是...在问题的 __init__
方法(或其他任何地方)中,我似乎无法访问与 app
相关的任何内容,它会抛出 classes_app.py", line 129, in __init__ - print(app) NameError: name 'app' is not defined
到底为什么?这两个 classes 没有从其他人那里继承任何东西,并且在层次上是 'equals',只是程序中的两个平均 classes(实际上,Question 是创建 Check 实例的那个!) .一个人认识全球而其他人不认识?
最令人难以置信的是:Check
class 中没有 global
关键字,它仍然有效?
到目前为止我已经尝试过:
1 - 在全局范围内的 main
函数之外声明 app = MainWindow(window)
。没有。
2 - 在程序的每个函数中使用 global
关键字来查看他们是否得到它。没有。
3 - 将 main
函数放在代码的最顶部,这样它就是第一个
app
的声明似乎也没什么作用。
4 - 上述解决方案和反复试验恶作剧的任意组合。
5 - 牺牲一块主板给python globals 的代码女神。
请注意,我是 python 的新手,所以我可能对全局变量的理解非常错误,或者完全不理解,但根据文档所说,用 global
关键字应该是一个全局变量,并且可以从代码中的所有函数和方法访问全局变量,对吗?
如果你问为什么我如此需要它来让 app = MainWindow(window)
成为全局的:会有一个全局函数来清理每个问题之间的小部件:
def destroy_widgets(parent):
for widget in parent.winfo_children():
widget.destroy()
所以在 classes 的方法中,我会像 destroy_widgets(app.frameChk)
那样称呼它。这是我第一次遇到这个问题。
我会 post 整个代码,但是所有这些 tkinter 定义都非常广泛。如果你们认为有必要,我当然会。
任何帮助或见解将不胜感激,在此先感谢,这个社区是黄金!
Definition/lifetime 个变量
关于这个:
Most mind-boggling: the Check class does NOT have the global keyword in it, and it still works?
您只需要 global
关键字来在本地上下文中创建或更改全局变量,see this answer。
此外,语句 global app
尚未创建变量 app
- 它仅在第一次赋值时创建。在您的示例中,这意味着 app
仅在此处创建:app = MainWindow(window)
。
如果 Question
在此语句之前创建(在您的示例中,通过 Tk()
或 MainWindow(window)
),则 app
尚不存在。
你可以在解释器中试试这个:
>>> global app
>>> print(app)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'app' is not defined
命名空间
另一个需要注意的重要事实:如果您的代码组织在不同的模块中,您必须注意命名空间。
例子
假设我们有两个 python 文件:first.py
和 second.py
:
first.py
的内容:
app = 5
second.py
的内容:
import first
print(first.app)
运行 这个有效:
$ python3 second.py
5
只放 print(app)
是行不通的,因为模块不同。