无法弄清楚 lambda 函数在我的 tkinter 项目中的作用

Can't figure out what lambda function does in my tkinter project

我使用 TkinterPython 中编写了一个简单的计算器代码。几乎每个函数都有效,但我似乎无法弄清楚 lambda 函数在我的项目中的作用。如果我添加它没有任何错误但如果我删除它会显示错误。

这里是错误指出的块

class Calc:
    def __init__(self):
        self.total = 0
        self.current = ''
        self.ip_val = True
        self.check_sum = False
        self.op = ''
        self.result = False

    def operation(self, op):
        self.current = float(self.current) #this line generates error
        if self.check_sum:
            self.valid_function()
        elif not self.result:
            self.total = self.current
            self.ip_val = True
        self.check_sum = True
        self.op = op
        self.result = False

这里是调用CALCclass运算方法的那一行

Button(calc, text='x^y', width=6, height=2, font=('arial', 20, 'bold'), bd=4, bg="gray20",
       command= res.operation('pow')).grid(row=1, column=5, pady=1)

错误信息

Traceback (most recent call last):
  File "T:/WorkSpace/PythonCourse/Day-6.py", line 235, in <module>
    command= res.operation('pow')).grid(row=1, column=5, pady=1)
  File "T:/WorkSpace/PythonCourse/Day-6.py", line 69, in operation
    self.current = float(self.current)
ValueError: could not convert string to float: ''

仅供参考,我知道如果我像下面这样初始化按钮 class(使用 lambda 函数)

Button(calc, text='x^y', width=6, height=2, font=('arial', 20, 'bold'), bd=4, bg="gray20",
       command= lambda: res.operation('pow')).grid(row=1, column=5, pady=1)

一切正常。

查询

我想解释一下这个 lambda 函数是如何解决这个错误的。而且,如果用户没有按下按钮,则该函数不应调用自身。这甚至如何编译?

考虑这行代码:

Button(..., command= res.operation('pow'))

它的行为与这两行代码完全相同:

result = res.operation('pow')
Button(..., command= result)

这就是 python 的工作原理。它不是 tkinter 独有的。当python看到x(y),大多数情况下会立即执行x

看到问题了吗? res.operation('pop') 在您创建按钮时立即调用函数, 而不是 在您单击按钮时。定义按钮时,需要将command属性设置为callable.

有几种方法可以告诉 tkinter 调用什么函数。如果你没有任何参数,你只需给它函数本身的名称:

Button(..., command=res.operation)

但是,在这种情况下,您需要传递一个参数,这样您就不能只将函数名称传递给命令。您需要同时传递名称和参数。这就是 lambda 的用武之地。lambda 创建一个新函数,并将该函数传递给 command 参数。

实际上,Button(..., ,command=lambda res.opeeration('pow'))与此大致相同:

def i_dont_care_what_the_name_is():
    res.operation('pow')
Button(..., command=i_dont_care_what_the_name_is)

请注意,这并不完全相同,但差异在本次讨论中并不重要。

底线是 lambda 提供了一种将可调用对象传递给函数或将其分配给属性或变量的简单方法。

郑重声明,获得相同结果的另一种方法是使用 functools.partial。有些人更喜欢 lambda,尽管使用 lambda 不需要像 functools.partial 那样的额外导入。