使用 Tkinter 按钮了解 Python Lambda 行为

Understanding Python Lambda behavior with Tkinter Button

我想了解按钮如何使用 lambda 工作。 我有以下 Python 代码:

from tkinter import *

def comando_click(mensagem):
    print(mensagem)

menu_inicial = Tk()
menu_inicial.geometry("500x250+200+200")

botao = Button(menu_inicial, text = "Executar", command=comando_click("Nova_Mensagem"))
botao.pack()

menu_inicial.mainloop()

但是当我点击它时我的按钮不起作用,当我 运行 代码时它只在控制台中显示一次打印,我在问题中添加了一些打印:

Problem Picture one

好吧,当我在按钮中使用 Lambda 函数时,它似乎起作用了,我真的很想知道为什么。

Lambda working button Picture one

我刚刚向按钮添加了 lambda :

botao = Button(menu_inicial, text = "Executar", command=lambda:comando_click("Nova_Mensagem"))

Lambda working button Picture two

为什么对 lambda 有效? 如果没有 lambda,它也不应该工作,因为 lambda 基本上是一个匿名函数?

我非常想知道它为什么起作用,谢谢大家的帮助:)

编辑:谢谢你们,现在我终于明白发生了什么以及Python是如何工作的。非常感谢大家 :D

在此代码中:

command=comando_click("Nova_Mensagem")

您调用了 comando_click 函数一次,并将结果 (None) 赋给了 command 参数。调用 command 时什么也不会发生(实际上你应该得到一个 TypeError 异常,因为 None 不可调用)。

在此代码中:

command=lambda:comando_click("Nova_Mensagem")

您实际上还没有调用 comando_click -- 您创建了一个新函数(使用 lambda),该函数将在调用时依次调用 comando_click。每次单击按钮时,都会调用您的新函数。

如果 lambda 令人困惑,您可以像这样使用 def 做完全相同的事情:

def button_command():
    comando_click("Nova_Mensagem")

...

command=button_command  # no ()!  we don't want to actually call it yet!

当您想创建一个不需要名称的小型一次性函数(例如,您想要创建一个函数调用带有特定参数的另一个函数,就像您在此处所做的那样。

问题是 comando_click("Nova_Mensagem") 您正在执行函数。所以命令=None.

在第二种情况下 lambda:comando_click("Nova_Mensagem") 返回一个内部调用 comando_click("Nova_Mensagem").

的 lambda

修复:只需输入 command=comando_click.

如果你想用参数个性化 lambda,你可以这样写:

def handler(args):
    def custom_handler():
        print(args)
    return custom_handler

botao = Button(menu_inicial, text = "Executar", command=handler("my custom string"))

当你使用()和一个函数名(func(args))时,那么它立即calling/invoking函数而python正在执行该行,你不想要那个。您只想在单击按钮时调用该函数。 tkinter 将在内部为您调用该函数,您只需提供函数名称即可。

为什么要用lambda把它看成一个函数就是returns另一个函数,你的代码可以加长为:

func  = lambda: comando_click("Nova_Mensagem")
botao = Button(menu_inicial, text = "Executar", command=func)

func是函数名,如果你想调用它,你会说func()。当你说 command=comando_click("Nova_Mensagem") 然后 commandcommand click 返回的值(因为你用 () 调用函数),这是 None 如果我' m没有错,如果给定的值为None,则不会被tkinter调用。因此,由于 () ,您的函数仅执行一次,并且作为调用该函数的结果,您在事件循环开始处理事件之前分配了函数调用 (None) 的值。

其他一些方法:

  • 使用 partial 来自 functools:
from functools import partial

botao = Button(.....,command=partial(comando_click,"Nova_Mensagem"))
  • 使用助手函数:
def helper(args):
    def comando_click():
        print(args)

    return comando_click

botao = Button(...., command=helper("Nova_Mensagem"))

IMO,lambdas 是继续调用带有参数的函数的最简单方法。