【问题标题】:Understanding Python Lambda behavior with Tkinter Button [duplicate]使用 Tkinter 按钮了解 Python Lambda 行为 [重复]
【发布时间】:2022-01-21 03:50:48
【问题描述】:

我想了解按钮是如何使用 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

【问题讨论】:

标签: python python-3.x tkinter tk tkinter-button


【解决方案1】:

当您将() 与函数名称(func(args))一起使用时,它会在 python 执行该行时立即调用/调用该函数,您不希望这样。您只想在单击按钮时调用该函数。 tkinter 将在内部为您调用该函数,您只需提供函数名称即可。

为什么要使用lambda把它想象成一个返回另一个函数的函数,你的代码可以加长为:

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

func 是函数名,如果你想调用它,你会说func()。当你说command=comando_click("Nova_Mensagem") 时,command 的返回值是command click(因为你用() 调用函数),它是None,如果我没记错的话,如果给定的值是@ 987654333@,不会被tkinter调用。因此,由于(),您的函数只执行一次,并且由于调用该函数,您在事件循环开始处理事件之前分配了函数调用的值(None)。

其他一些方法:

  • 使用来自functoolspartial
from functools import partial

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

    return comando_click

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

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

【讨论】:

    【解决方案2】:

    在这段代码中:

    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!
    

    lambda 表达式只是当您想要创建一个不需要名称的小型一次性函数时使用 def 的替代方法(例如,您想要创建一个调用另一个具有特定名称的函数的函数)论据,就像你在这里做的那样)。

    【讨论】:

    • "..事实上你应该得到一个 TypeError 异常,因为 None 是不可调用的..":我不认为 tkinter 会打扰调用 NoneType 对象反正
    • 似乎是 tkinter imo 中的一个反特征(它应该让你知道你的按钮定义错字了),但我从未使用过它:)
    • @Samwise:这不是反特征。出于某些原因,您可能希望或需要将命令设置为 None
    【解决方案3】:

    问题在于您正在使用comando_click("Nova_Mensagem") 执行该函数。所以 command=None。

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

    修复:只需输入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"))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-06
      • 2019-07-14
      • 1970-01-01
      • 2017-10-27
      • 1970-01-01
      • 2021-02-14
      相关资源
      最近更新 更多