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

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

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


当前回答

函数这是一种非官僚化的创建函数的方法。

就是这样。例如,假设你有一个主要函数,需要对值平方。我们来看看传统的方法和的方法

传统的方法:

def main():
...
...
y = square(some_number)
...
return something

def square(x):
    return x**2

方式:

def main():
...
square = lambda x: x**2
y = square(some_number)
return something

看到区别了吗?

Lambda函数非常适合用于列表,比如列表推导式或映射。事实上,列表理解是一种使用lambda来表达自己的“python”方式。例:

>>>a = [1,2,3,4]
>>>[x**2 for x in a]
[1,4,9,16]

让我们看看每个语法元素的含义:

[]:“给我一个清单” X **2:“使用这个新诞生的函数” 对于a中的x: "into each element in a"

很方便吧?创建这样的函数。让我们用lambda重写它:

>>> square = lambda x: x**2
>>> [square(s) for x in a]
[1,4,9,16]

现在让我们使用map,这是同样的东西,但更语言中立。Maps有两个参数:

(i)一个功能

(ii)可迭代对象

给你一个列表,其中每个元素它是应用于可迭代对象的每个元素的函数。

使用map,我们会得到:

>>> a = [1,2,3,4]
>>> squared_list = map(lambda x: x**2, a)

如果你掌握了lambdas和映射,你将拥有以简洁的方式操作数据的强大能力。Lambda函数既不晦涩,也不影响代码的清晰性。不要把难的东西和新东西混为一谈。一旦你开始使用它们,你就会发现非常清楚。

其他回答

Lambdas通常与函数式编程风格密切相关。通过将函数应用于某些数据并合并结果来解决问题,这是谷歌用于实现其大多数算法的思想。

以函数式编程风格编写的程序很容易并行化,因此在现代多核机器中变得越来越重要。 所以简而言之,不,你不应该忘记他们。

如上所述,Python中的lambda操作符定义了一个匿名函数,而Python中的函数是闭包。重要的是不要将闭包的概念与操作符lambda混淆,后者对它们来说只是句法上的美沙酮。

当我几年前开始使用Python时,我经常使用lambda,认为它们很酷,还有列表推导式。然而,我编写并维护了一个用Python编写的大型网站,其中有几千个功能点。我从经验中了解到,lambdas可能可以用来创建原型,但除了节省一些键,它不能提供任何内联函数(命名闭包),有时也不能。

基本上这可以归结为几点:

it is easier to read software that is explicitly written using meaningful names. Anonymous closures by definition cannot have a meaningful name, as they have no name. This brevity seems, for some reason, to also infect lambda parameters, hence we often see examples like lambda x: x+1 it is easier to reuse named closures, as they can be referred to by name more than once, when there is a name to refer to them by. it is easier to debug code that is using named closures instead of lambdas, because the name will appear in tracebacks, and around the error.

这就有足够的理由将它们集中起来,并将它们转换为命名闭包。然而,我对匿名闭包还有另外两个不满。

第一个不满是,它们只是又一个不必要的关键字,把语言弄得乱七八糟。

第二个不满是更深层次的,在范式层面上,也就是说,我不喜欢他们提倡一种函数式编程风格,因为这种风格不如消息传递、面向对象或过程式风格灵活,因为lambda微积分不是图灵完备的(幸运的是,在Python中,我们仍然可以在lambda内部突破这种限制)。我觉得lambdas推崇这种风格的原因是:

这里有一个隐式的返回,即它们看起来像“应该”是函数。 它们是另一种更显式、更可读、更可重用和更通用的机制——方法——的状态隐藏机制的替代方案。

我努力编写无lambda的Python,并在看到lambdas时删除lambdas。我认为如果没有lambdas, Python将是一种更好的语言,但这只是我的个人观点。

我使用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不同(后者更强大),但您确实可以用它们做很多神奇的事情。

我已经使用Python好几年了,我从来没有遇到过需要lambda的情况。实际上,正如教程所述,这只是语法糖。