我一直密切关注YouTube视频,以便使用tkinter创建屏幕键盘。
我理解发生的大部分事情;在列表中创建我们的按钮并循环浏览这些按钮,在最佳位置插入行以创建美观的键盘。
我遇到这个任务的唯一问题是,当我点击一个按钮时,按钮的文本会通过tkinter插入到一个Entry框中。
我们这样做的方法是给按钮分配一个命令,按下它后,调用一个匿名函数,将我们按下的按钮分配给'x'参数。然后,我们将此参数传递给另一个方法,并将值插入Entry小部件。
我试图理解,为什么我们不能只传递按钮本身,而是我们必须将按钮分配给参数......
self.textbox = textbox
row=0
col=0
buttons = [
'1','2','3','4','5','6','7','8','9','0',
'q','w','e','r','t','y','u','i','o','p',
'a','s','d','f','g','h','j','k','l',
'z','x','c','v','b','n','m','end']
for button in buttons:
# why not the following command instead?
# command = lambda: self.command(button)
command = lambda x=button: self.callback(x)
if button != 'end':
tk.Button(self, text=button, width=5,
command=command).grid(row=row, column=col)
col+=1
if col > 9:
col=0
row+=1
def command(self, button):
x = button
self.callback(x)
def callback(self, value):
self.textbox.insert(tk.END, value)
使用上面的代码,我可以成功地将所需的值插入到我的条目小部件中。但是,如果我们使用我已注释掉的代码,它会将“end”插入到条目小部件中。
我试图将lambda函数复制到一个单独的方法中,但我仍然在我的条目小部件中插入一个'end'。
# using the commented code above and passing in button as the parameter
def command(self, button):
x = button
self.callback(x)
def callback(self, value):
self.textbox.insert(tk.END, value)
我想如果我能够将该函数复制到非匿名函数中,那么它就可以工作,但显然不是。
我的lambda函数到底是做什么的,有没有办法通过使用非匿名函数(即方法)来复制它?
答案 0 :(得分:1)
的问题
for button in buttons:
command = lambda: self.command(button)
是command
等于lambda: self.command(button)
,它被传递给Button
构造函数。
因此Button
实例的命令等于lambda: self.command(button)
。
您会认为self.command(button)
已被评估,并被以下结果取代:
def command(self, button):
x = button
self.callback(x)
但是,没有理由这样做:因为self.command(button)
是<{1}}函数内的 ,所以当 {时,它将评估 {1}} 将被称为。
因此,在执行如此创建的lambda
函数时,lambda
将被评估为分配的最后一个值,不会评估时的值lambda
已创建。
因此,在该循环之后,所有这些button
函数都将具有相同的行为,并且其内部的lambda
将指向同一个lamda
实例。
如果要使用方法而不是button
,可以将Button
方法包装在命令构建器中:
lambda
然后只需调用该方法即可获得预期的命令:
command
这个工作的原因是,def build_command(self, button):
def command():
self.callback(button)
return command
是command = self.build_command(button)
的本地变量,内部button
“将此变量继承到自己的局部变量字典中(由build_command
)。
本地词典将不受外部变化的影响。
答案 1 :(得分:1)
以下示例代码显示右腿正在解释的内容。 Python懒洋洋地评估数字:
functions1 = []
functions2 = []
for number in range(0,5):
functions1.append(lambda x=number: print(x))
functions2.append(lambda : print(number))
for function in functions1:
function()
for function in functions2:
function()
因此, functions2 仅打印4.而lambda x=number
立即评估数字,并将其值设置为x。