为何含tkinter与全局变量的Python函数始终返回0?
Tkinter按钮点击返回值异常问题
问题描述
以下代码中,ask2函数无论点击哪个按钮始终返回0,预期点击第一个按钮返回0、点击第二个按钮返回2,请问问题出在哪?
from tkinter import* root = Tk() root.title("Example") root.geometry("1000x250") root['bg']="black" def ask2(question,var1,var2): ans = 0 def button1(): global ans bt1.destroy() bt2.destroy() lb.destroy() root.quit() ans = 0 def button2(): global ans bt1.destroy() bt2.destroy() lb.destroy() root.quit() ans = 1 lb = Label(root,text=question, bg="black", fg="white", font=("Determination (RUS BY LYAJKA)",28)) bt1 = Button(text=var1, justify=CENTER, relief=SOLID, bg="black", fg="white", font=("Determination (RUS BY LYAJKA)",20), command=button1, disabledforeground="yellow") bt2 = Button(text=var2, justify=CENTER, relief=SOLID, bg="black", fg="white", font=("Determination (RUS BY LYAJKA)",20), command=button2) lb.pack(side=TOP) bt1.pack(side=LEFT) bt2.pack(side=RIGHT) root.mainloop() if ans == 0: return(0) else: return(2) print(ask2("Question","Answer 1", "Answer 2"))
问题原因
核心问题是global ans的使用错误:
ask2函数里的ans是局部变量,但内部嵌套的button1和button2函数用了global声明,这会让它们去修改全局作用域里的ans,而不是ask2里的局部ans。- 当
root.mainloop()结束后,ask2判断的是自己一开始初始化的局部ans(值为0),所以不管点击哪个按钮,最终都会返回0。
解决方案
可以用两种简单的方式修复:
方法1:用nonlocal代替global
把button1和button2里的global ans改成nonlocal ans,这样就能让嵌套函数修改外层ask2函数的局部变量:
def ask2(question,var1,var2): ans = 0 def button1(): nonlocal ans # 替换global为nonlocal bt1.destroy() bt2.destroy() lb.destroy() root.quit() ans = 0 def button2(): nonlocal ans # 替换global为nonlocal bt1.destroy() bt2.destroy() lb.destroy() root.quit() ans = 1 # 后续代码不变...
方法2:用可变对象存储ans(兼容Python2)
如果需要兼容Python2(没有nonlocal),可以用列表这种可变对象来存ans,因为可变对象的修改会影响外层作用域:
def ask2(question,var1,var2): ans = [0] # 用列表存值 def button1(): bt1.destroy() bt2.destroy() lb.destroy() root.quit() ans[0] = 0 # 修改列表元素 def button2(): bt1.destroy() bt2.destroy() lb.destroy() root.quit() ans[0] = 1 # 修改列表元素 # 后续代码不变... root.mainloop() if ans[0] == 0: # 取列表元素判断 return(0) else: return(2)
这样修改后,点击第一个按钮会返回0,点击第二个按钮返回2,符合预期。
内容的提问来源于stack exchange,提问作者Denis Pasishnichenko
相关产品推荐
相关产品推荐

