我正在为计算器编写程序,但我遇到了一个小问题。 每当我按下其中一个按钮时,它每次都会增加9,即使它应该是i(来自for循环)。 请有人告诉我为什么它总是9岁吗?
代码 -
import tkinter
plus = True
numbers = 0
def main():
def numButton(i):
global numbers
if plus == False:
numbers-=i
else:
numbers+=i
def quitHandler():
root.destroy()
def entryHandler():
global numbers
numbers+=int(text.get())
text.set("")
def printHandler():
text2.set(numbers)
def restartHandler():
global numbers
root.destroy()
plus = True
numbers = 0
main()
def plusHandler():
global plus
plus = True
def minusHandler():
global plus
plus = False
root = tkinter.Tk()
frame = tkinter.Frame(root).pack(side=tkinter.TOP)
text = tkinter.IntVar()
text2 = tkinter.IntVar()
text.set("")
text2.set("")
tkinter.Entry(frame,bd =8,textvariable=text).pack()
tkinter.Button(frame,padx=8,pady=8,bd=8,text="Enter",command=entryHandler).pack()
tkinter.Button(frame,padx=8,pady=8,bd=8,text="Quit",command=quitHandler).pack(side=tkinter.RIGHT)
tkinter.Button(frame,padx=8,pady=8,bd=8,text="Restart",command=restartHandler).pack(side=tkinter.RIGHT)
tkinter.Button(frame,padx=8,pady=8,bd=8,text="Print",command=printHandler).pack(side=tkinter.LEFT)
tkinter.Entry(frame,bd =8,textvariable=text2).pack(side=tkinter.LEFT)
_padx = 16
_pady = 16
_bd = 8
for i in range (1,10):
tkinter.Button(frame, padx = _padx, pady = _pady, bd = _bd, text = str(i), command = lambda: numButton(i)).pack(side = tkinter.LEFT)
tkinter.Button(frame,padx=8,pady=8,bd=8,text="+",command=plusHandler).pack(side=tkinter.LEFT)
tkinter.Button(frame,padx=8,pady=8,bd=8,text="-",command=minusHandler).pack(side=tkinter.LEFT)
main()
有人还可以告诉我如何将所有内容放在此网站上的代码内容中,我无法弄明白,网站帮助显示我的方式无效(或请管理员修复)。
tkinter.Button(frame, padx = _padx, pady = _pady, bd = _bd, text = str(i), command = lambda i=i: numButton(i)).pack(side = tkinter.LEFT)
必须在lamda之后添加i = i。 有人可以向我解释一下i = i的事情吗?
由于
答案 0 :(得分:1)
command = lambda: numButton(i)
这不会在lambda创建时查找i
的值并将其插入到函数中。当调用lambda时,然后它会查找i
。到那时i
总是9
。
有几种方法可以解决这个问题,所有这些方法都集中在确保在i
的创建时间而不是执行时间查找command
。我使用的是functools.partial
,一个用于将函数与参数相关联的工具:
from functools import partial
...
command=partial(numButton, i)
你也可以使用默认参数,这是一种kludgy:
command=lambda i=i: numButton(i)
或者写一个工厂功能:
def closure_maker(i):
def closure():
numButton(i)
return closure
...
command=closure_maker(i)
答案 1 :(得分:0)
用于命令的lambda函数引用变量i
:
for i in range (1,10):
tkinter.Button(frame, padx = _padx, pady = _pady, bd = _bd, text = str(i),
command = lambda: numButton(i)).pack(side = tkinter.LEFT)
执行命令并运行lambda函数时,它会选择按钮编号i
。但是那时,当执行lambda函数时,i
包含值9
(i
循环之后的值for
结束了创建按钮完成。
要解决此问题,请确保lambda函数不会共享同一个全局变量。一种方法是使用创建新局部范围的函数:
def numCommand(x):
return (lambda: numButton(x))
for i in range (1,10):
tkinter.Button(frame, padx = _padx, pady = _pady, bd = _bd, text = str(i),
command = numCommand(i)).pack(side = tkinter.LEFT)
此处每个lambda函数都引用其x
调用中自己的numCommand()
变量。