如何在没有全局关键字的情况下使用 tkinter 中的按钮更改全局变量?
How to change a global variable without global keyword using a button in tkinter?
我正在制作剪刀石头布程序,我需要更改当他们单击按钮时轮到谁,但我不想使用 global 关键字,因为该程序在函数内部。
这是我在不使用 global 关键字的情况下尝试执行的操作的示例:
from tkinter import *
root = Tk()
var = 1
def buttonClick():
global var
var += 1
print(var)
button = Button(root, text="button", command=buttonClick).pack()
root.mainloop()
我试过写 command=(var += 1)
但没有成功。
如果整个脚本在一个函数中(包括 buttonClick()
函数)则使用 nonlocal
关键字:
def buttonClick():
nonlocal var
var += 1
print(var)
如果函数没有嵌套,唯一的方法是在两个函数中创建一个全局变量和global
关键字。
不,你确实不能。例如,如果它是一个列表,则可以更改全局 var
的 contents。然后您可以将命令编写为没有完整函数体的 lambda 表达式。
但这根本不是最好的设计。
Tkinter 事件模型与 Python 对象模型结合得很好——在某种程度上,您可以包含class 中与 UI 相关的所有内容 - 即使它只有一个实例 - 这样你的程序就可以以“self.var”的形式访问 var,以“self.button_click 的形式访问命令]”,如果他们不应该把事情搞砸的危险很小。
只是您找到的大多数文档和教程都会有继承 tkinter 对象本身并在现有 classes 之上添加您的元素的 OOP 示例。我强烈反对这种方法:tkinter classes 已经足够复杂了,有数百个方法和属性——即使是一个复杂的程序也只需要几十个内部状态让你担心。
最好的事情是联系:您想要访问的所有内容都应该成为您 class 的成员。在程序的开始,您实例化 class,这将创建 UI 元素并保留对它们的引用:
import tkinter as tk # avoid wildcard imports: it is hard to track what is available on the global namespace
class App:
def __init__(self):
self.root = tk.Tk()
self.var = 1
# keep a refernce to the button (not actually needed, but you might)
self.button = tk.Button(self.root, text="button", command=self.buttonClick)
self.button.pack()
def buttonClick(self):
# the button command is bound to a class instance, so
# we get "self" as the object which has the "var" we want to change
self.var += 1
print(self.var)
def run(self):
self.root.mainloop()
if __name__ == "__main__": # <- guard condition which allows claases and functions defined here to be imported by larger programs
app = App()
app.run()
是的,你可以。这里有一个 hacky 的方式来说明它 可以 完成,尽管它肯定不是做这些事情的推荐方式。 免责声明:我的想法来自an answer to a related question。
from tkinter import *
root = Tk()
var = 1
button = Button(root, text="button",
command=lambda: (globals().update(var=var+1), print(var)))
button.pack()
root.mainloop()
我正在制作剪刀石头布程序,我需要更改当他们单击按钮时轮到谁,但我不想使用 global 关键字,因为该程序在函数内部。
这是我在不使用 global 关键字的情况下尝试执行的操作的示例:
from tkinter import *
root = Tk()
var = 1
def buttonClick():
global var
var += 1
print(var)
button = Button(root, text="button", command=buttonClick).pack()
root.mainloop()
我试过写 command=(var += 1)
但没有成功。
如果整个脚本在一个函数中(包括 buttonClick()
函数)则使用 nonlocal
关键字:
def buttonClick():
nonlocal var
var += 1
print(var)
如果函数没有嵌套,唯一的方法是在两个函数中创建一个全局变量和global
关键字。
不,你确实不能。例如,如果它是一个列表,则可以更改全局 var
的 contents。然后您可以将命令编写为没有完整函数体的 lambda 表达式。
但这根本不是最好的设计。
Tkinter 事件模型与 Python 对象模型结合得很好——在某种程度上,您可以包含class 中与 UI 相关的所有内容 - 即使它只有一个实例 - 这样你的程序就可以以“self.var”的形式访问 var,以“self.button_click 的形式访问命令]”,如果他们不应该把事情搞砸的危险很小。
只是您找到的大多数文档和教程都会有继承 tkinter 对象本身并在现有 classes 之上添加您的元素的 OOP 示例。我强烈反对这种方法:tkinter classes 已经足够复杂了,有数百个方法和属性——即使是一个复杂的程序也只需要几十个内部状态让你担心。
最好的事情是联系:您想要访问的所有内容都应该成为您 class 的成员。在程序的开始,您实例化 class,这将创建 UI 元素并保留对它们的引用:
import tkinter as tk # avoid wildcard imports: it is hard to track what is available on the global namespace
class App:
def __init__(self):
self.root = tk.Tk()
self.var = 1
# keep a refernce to the button (not actually needed, but you might)
self.button = tk.Button(self.root, text="button", command=self.buttonClick)
self.button.pack()
def buttonClick(self):
# the button command is bound to a class instance, so
# we get "self" as the object which has the "var" we want to change
self.var += 1
print(self.var)
def run(self):
self.root.mainloop()
if __name__ == "__main__": # <- guard condition which allows claases and functions defined here to be imported by larger programs
app = App()
app.run()
是的,你可以。这里有一个 hacky 的方式来说明它 可以 完成,尽管它肯定不是做这些事情的推荐方式。 免责声明:我的想法来自an answer to a related question。
from tkinter import *
root = Tk()
var = 1
button = Button(root, text="button",
command=lambda: (globals().update(var=var+1), print(var)))
button.pack()
root.mainloop()