我在试着找出Python的lambda。lambda是那些在现实生活中应该被遗忘的“有趣”语言项之一吗?

我确信有一些边缘情况可能需要它,但是考虑到它的模糊性,它在未来版本中被重新定义的可能性(我基于它的各种定义的假设)以及降低的编码清晰度——应该避免它吗?

这让我想起了C类型的溢出(缓冲区溢出)——指向顶部变量并重载以设置其他字段值。这感觉有点像技术人员的表演,但维护程序员的噩梦。


当前回答

两行总结:

闭包:非常有用。学习它们,利用它们,热爱它们。 Python的lambda关键字:不必要,偶尔有用。如果你发现自己在用它做任何复杂的事情,把它放在一边,定义一个真正的函数。

其他回答

在我看来,lambda的一个好处是,它可以将简单表单的计算推迟到需要值时才进行。让我解释一下。

许多库例程的实现使得它们允许某些参数被调用(lambda是其中之一)。其思想是,实际值只在将要使用它的时候计算(而不是在调用它的时候)。一个(虚构的)例子可能有助于说明这一点。假设你有一个程序,它将记录一个给定的时间戳。您希望例程使用当前时间减去30分钟。你会这么说的

log_timestamp(datetime.datetime.now() - datetime.timedelta(minutes = 30))

现在假设实际函数只在某个事件发生时才被调用,并且您希望仅在该事件发生时计算时间戳。你可以这样做

log_timestamp(lambda : datetime.datetime.now() - datetime.timedelta(minutes = 30))

假设log_timestamp可以像这样处理可调用对象,它将在需要时计算这个值,届时您将获得时间戳。

当然,还有其他方法可以做到这一点(例如使用operator模块),但我希望我已经传达了这一点。

更新:这里有一个更具体的现实世界的例子。

更新2:我认为这是所谓的“坦克”的一个例子。

只是函数的一种奇特说法。除了它的名字,它没有什么晦涩、吓人或神秘的地方。当你读到下面这行,在脑海中用函数替换lambda:

>>> f = lambda x: x + 1
>>> f(3)
4

它只是定义了一个关于x的函数。其他一些语言,比如R,显式地说:

> f = function(x) { x + 1 }
> f(3)
4

你看到了什么?这是编程中最自然的事情之一。

我使用lambda来创建包含参数的回调。在一行中编写lambda比编写一个方法来执行相同的功能更简洁。

例如:

import imported.module

def func():
    return lambda: imported.module.method("foo", "bar")

相对于:

import imported.module

def func():
    def cb():
        return imported.module.method("foo", "bar")
    return cb

Lambdas实际上是非常强大的构造,它源于函数式编程的思想,而且在Python的近期内,它绝不可能被轻易地修改、重新定义或删除。它们可以帮助您编写更强大的代码,因为它允许您将函数作为参数传递,因此函数是一等公民。

Lambdas确实容易让人困惑,但一旦获得了扎实的理解,你就可以写出像这样干净优雅的代码:

squared = map(lambda x: x*x, [1, 2, 3, 4, 5])

上面的代码行返回列表中数字的平方的列表。当然,你也可以这样做:

def square(x):
    return x*x

squared = map(square, [1, 2, 3, 4, 5])

显然,前一种代码更短,如果您打算只在一个地方使用map函数(或任何以函数作为参数的类似函数),则尤其如此。这也使代码更加直观和优雅。

另外,正如@David Zaslavsky在他的回答中提到的,列表推导并不总是正确的方法,尤其是当你的列表必须从一些晦涩的数学方法中获取值时。

从更实际的角度来看,lambdas最近对我来说最大的优势之一是在GUI和事件驱动编程方面。如果你看一下Tkinter中的回调,它们所接受的参数就是触发它们的事件。如。

def define_bindings(widget):
    widget.bind("<Button-1>", do-something-cool)

def do-something-cool(event):
    #Your code to execute on the event trigger

现在如果你有一些论点要通过呢?简单到传递2个参数来存储鼠标单击的坐标。你可以简单地这样做:

def main():
    # define widgets and other imp stuff
    x, y = None, None
    widget.bind("<Button-1>", lambda event: do-something-cool(x, y))

def do-something-cool(event, x, y):
    x = event.x
    y = event.y
    #Do other cool stuff

现在,您可以争辩说这可以使用全局变量来完成,但是,如果全局变量只用于一个特定的位置,您真的想要担心内存管理和泄漏吗?那只是糟糕的编程风格。

简而言之,lambdas是很棒的,永远不应该被低估。尽管Python lambdas与LISP lambdas不同(后者更强大),但您确实可以用它们做很多神奇的事情。

lambdas在GUI编程中非常有用。例如,假设您正在创建一组按钮,并且希望使用单个参数化回调,而不是每个按钮使用唯一的回调。Lambda让你轻松完成:

for value in ["one","two","three"]:
    b = tk.Button(label=value, command=lambda arg=value: my_callback(arg))
    b.pack()

(注意:虽然这个问题是专门问lambda的,但你也可以使用functools。以获得相同类型的结果)

另一种方法是为每个按钮创建单独的回调,这可能导致重复的代码。