我们知道在 Python 中定义一个函数使用 def 关键字。实际上,Python 中还有另一种定义函数的语法,使用 lambda 关键字即可定义一个短小的 匿名函数

lambad 表达式的定义语法

下面是一个使用 lambda 关键字定义 匿名函数 的简单示例,用于对传进来的两个参数进行求和:

1
>>> lambda x, y: x + y

其中,冒号(:)左侧的 x, y 变量分别是 匿名函数 的两个参数,而冒号(:)右侧的表达式 x + y 将作为 匿名函数返回值 进行返回(这个过程是自动的,无需显式的写 return 语句进行返回,写了反而会报错)。

那么该如何调用这个 匿名函数 呢?请看下面的代码:

1
2
>>> (lambda x, y: x + y)(2, 3)
5

要想调用 匿名函数,只需要在 匿名函数 最外层给它加上一个括号,然后就能像调用普通函数一样的语法,使用 (参数1, 参数2) 的形式调用它了。 在 Python 控制台执行以上代码可以得到正确的求和结果 5

以上的 匿名函数 的定义和执行过程,如果使用普通函数来完成,代码如下:

1
2
3
4
>>> def add(x, y):
... return x + y
>>> add(2, 3)
5

经过对比,我们可以发现,使用 def 的普通函数需要 3 行才能搞定的事情,使用 匿名函数 只需要 1 行就可以了。

lambda 关键字定义的 匿名函数 只是一个 Python 的语法糖,它与 def 关键字定义的函数并无本质区别。不过需要注意的是,在 匿名函数 中,只允许定义单一的表达式,而不能定义其他语句,并且表达式的结果会被当作函数的返回值进行返回,因此 匿名函数 也被称作 lambda 表达式

在 Python 中函数也是对象,因此我们可以将函数赋值给一个变量,然后通过这个变量来调用函数。

1
2
3
>>> add = lambda x, y: x + y
>>> add(2, 3)
5

事实上,这种通过变量引用来调用 匿名函数 的方式才是我们在实际编码过程中用的更多的方式。

lambda 表达式的应用

下面我来介绍一下 匿名函数 的应用场景。

假如我们有一个由 元组 组成的 列表,我们需要对其进行排序,此时可以使用 Python 内置的 sorted 函数:

1
2
3
>>> li = [(1, 'Python'), (3, 'JavaScript'), (2, 'Go')]
>>> sorted(li)
[(1, 'Python'), (2, 'Go'), (3, 'JavaScript')]

可以看到,对 列表 使用 sorted 函数对其进行排序以后,其排序顺序是根据每个元组中第一个元素的大小进行排序的。那么如果我们想要根据元组的第二个元素按照字母顺序进行排序呢?这个时候,就可以用到 匿名函数 了。

1
2
3
4
>>> li = [(1, 'Python'), (3, 'JavaScript'), (2, 'Go')]
>>> sorted(li, key=lambda x: x[1])
[(2, 'Go'), (3, 'JavaScript'), (1, 'Python')]
>>>

sorted 函数接收一个参数 key 可以用来作为排序对象的排序依据,这个参数必须是一个可调用对象,所以通常我们可以定义一个函数来处理。但是一般来说这样的函数只会使用一次,并且这个示例所需的函数足够短小,此时正是使用 匿名函数 的最佳时机。

def 关键字定义的函数一样,使用 lambda 关键字定义的 匿名函数 同样支持嵌套。下面展示一个 lambda 表达式 版本的 闭包函数

1
2
3
4
>>> make_add = lambda x: lambda y: x + y
>>> add = make_add(2)
>>> add(3)
5

我在此必须强调一点,这种嵌套的写法虽然语法上是支持的,但在实际工作中千万不要这样来写,如果项目中充斥着大量的这种代码,那么这个项目将变得难以维护。给出这个示例,我只是想鼓励大家对于一个新接触的语法可以多进行尝试,这样才能进步得更快,同时获得更多的乐趣。

在 Python 中对于 匿名函数 的使用,我的观点是,只有需要一个非常短小且只在一处调用的函数时才使用,不然代码将会变得花里胡哨而难以维护。

匿名函数 的诸多限制至使它只能完成一个简单的工作,不过这也正是 匿名函数 的初衷,至于许多繁琐的工作,还是交给 def 去做吧。