【问题标题】:Can't figure out what lambda function does in my tkinter project无法弄清楚 lambda 函数在我的 tkinter 项目中的作用
【发布时间】:2021-04-14 10:01:35
【问题描述】:

我使用 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

这是调用CALC类的操作方法的那行代码。

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: ''

仅供参考,我知道如果我像下面这样初始化 Button 类(使用 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 函数是如何解决这个错误的。而且,如果用户不按下按钮,该函数也不应该调用自身。这怎么编译?

【问题讨论】:

  • lambda 有点像函数定义,当您定义一个函数时,您还可以在该定义中调用另一个函数。并且定义中的函数只有在定义的函数被调用后才会被调用,所以当你在函数末尾添加()时你正在调用它,而 lambda 是不允许立即调用的定义跨度>
  • 你知道command=res.operation('pow')会立即执行res.operation('pow'),而不是在按钮被点击的时候?
  • 好吧,你怎么知道有 lambda 这样的东西?当你回到那个信息源并检查它的解释时发生了什么?另外,当您尝试将python what is a lambda 放入搜索引擎时发生了什么?解释基本概念的含义以及它们是如何工作的,这不是 Stack Overflow 的主题。您应该尝试查看现有的教程和文档,如果您仍然感到困惑,请尝试实际讨论论坛,例如 Reddit 或 Quora。
  • 你到底有什么不明白的? command 需要一个可调用的(即一个函数)。当您不使用 lambda 表达式时,您将传递 res.operation('pow') 的结果,而不是传递可调用的(函数)。 res.operation('pow') 总是返回None,但程序永远不会到达那个点,而是在self.current = float(self.current) 这一行出错,因为self.current 是一个空字符串。
  • " 而且如果用户不按下按钮,函数也不应该调用自己。这怎么编译?"什么?当您使用command= res.operation('pow')时,正在调用该函数。

标签: python tkinter button lambda


【解决方案1】:

考虑这行代码:

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 那样需要额外的导入。

【讨论】:

  • def i_dont_care_what_the_name_is(arg): 应该是def i_dont_care_what_the_name_is():
  • @acw1668:谢谢。我已经更新了答案。
  • 谢谢大家:)
猜你喜欢
  • 2021-10-24
  • 1970-01-01
  • 2017-09-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多