解密lambda表达式

时间:2017-09-12 13:28:55

标签: python lambda tkinter

我一直密切关注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函数到底是做什么的,有没有办法通过使用非匿名函数(即方法)来复制它?

2 个答案:

答案 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。