【问题标题】:What does the '=' operator mean when used in an lambda expression?'=' 运算符在 lambda 表达式中使用时是什么意思?
【发布时间】:2019-09-03 15:24:49
【问题描述】:

我试图弄清楚一行代码的作用,但我很难理解它是如何工作的。我大致了解 Python 中 lambda 表达式的用途、使用和限制,但是这行代码让我很困惑,我找不到任何其他答案来解决它。

我正在尝试为计算器创建多个按钮,当按下按钮时会出现相应的值。我不想制作 9 个单独的按钮,而是想使用列表理解来一次制作所有按钮(9 个按钮,计算器上的每个数字 1 个)。有关更多详细信息,请参见代码。

我真的不明白x=button_numlambda x=button_num: enter_number(x) 表达式中做了什么,以及为什么它只有在完全以这种方式编写时才有效。如果我使用表达式 lambda: enter_number(button_num) 而不是计算器只显示值 9,无论我按下哪个按钮。


# Function inserts value into calculator based on clicked button
def enter_number(x):
    if entry_box.get() == "O":  # Used to emulate that a calculator has a "0" initially
        entry_box.delete(0, 'end')
        entry_box.insert(0, str(x))
    else:
        length = len(entry_box.get())
        entry_box.insert(length, str(x))

# Generate buttons
button_numbers = [Button(width=4, text=str(button_num), font='times 15 bold', bd=5,
                         command=lambda x=button_num: enter_number(x)) for button_num in range(10)]

【问题讨论】:

  • 不是默认函数值吗?如果x 未通过,则使用button_num 的值作为x?

标签: python-3.x function tkinter lambda functional-programming


【解决方案1】:

为了扩展 Giovanni 的回答,其他提议的方法不起作用的原因是 lambda: enter_number(button_num) 将使用封闭范围(即列表理解)中的 button_num 的值。 button_num 的值随后会随着每个后续 lambda 变化,并以 9 结束。通常此时可以删除 button_num,但由于 lambda 依赖于它,因此它将保持其值 9。

然而,默认参数是在函数定义时评估的,而不是在函数调用时,所以它们不会成为这个问题的牺牲品。他是一个更书面的例子

button_num = 0
def command(x=button_num):
    print(x)
button_num = 1
command()

在上面的代码中,command() 将打印 0,而不是 1,因为 button_num 的值在用作默认参数时被保存。

【讨论】:

  • 因此,如果我理解正确,lambda 表达式中的x=button_num 实际上是设置默认值,并且由于您提到的默认参数的属性,每次按下按钮时 x 都是一个新值.感谢您的回复,为我解决了问题!
  • 这可能超出了这个问题的范围,但是是否可以这样写,这样你就可以在没有 lambda 的情况下使用常规函数?
  • 是的,你可以有一个 for 循环,并在 for 循环内定义一个函数,然后使用该函数作为命令创建一个 Button,而不是列表推导式,并将其附加到列表。您仍然需要确保将循环变量存储到另一个变量中,或者使用默认参数技巧来避免与 lambdas 相同的问题。
【解决方案2】:

lambdadef 非常相似,但没有名称。在这两种情况下,类似x=10 的东西都定义了一个名为x 的参数,默认值为10

例如,考虑这个简单的函数。

def foo(x=10):
    print("x: {}".format(x))

运行时会得到如下结果:

  • foo() 打印“x: 10”
  • foo(42) => 打印“x: 42”

lambda 类似于 def(不完全是,但对于本次讨论来说足够接近),除了函数是匿名的 - 它没有名称。然后,您可以将此函数分配给变量,或将其传递给期望传递函数的对象,例如在定义回调时。

例如,这会创建一个匿名函数并将其与名为foo 的变量相关联。然后,您可以像调用任何其他函数一样调用它。

foo = lambda x=10: print("x: {}".format(x))
foo()    # prints "x: 10"
foo(42)  # prints "x: 42"

lambda 是一种在您并不真正关心函数名称是什么时创建函数的便捷方式,例如在创建回调时。通过使用默认参数,您将变量的当前值绑定为给定参数的默认值。

【讨论】:

  • 感谢您的回答,非常翔实!有没有办法在不使用 lambda 的情况下编写我放入原始答案的 lambda 表达式?我试图这样做,但我做不到,因为我不知道如何在不使用 lambda 的情况下将“button_num”设置为默认参数。你需要一个辅助函数还是排序?
  • @ShockDoctor:在你的例子中,有几种方法可以做你想做的事。一种是使用 lambda,另一种是使用functools.partial。您还可以创建嵌套函数或使用函数工厂。然而,你不能做的是在不使用其中一种方法的情况下定义默认参数。
  • 太棒了!感谢您的帮助!
【解决方案3】:

与普通函数定义一样,您可以为 lambda 函数的输入设置默认值

foo = lambda x=3: x+5
foo()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-05-07
    • 2015-09-18
    • 2017-03-29
    • 2011-03-16
    • 2011-07-09
    • 2016-07-23
    • 1970-01-01
    相关资源
    最近更新 更多