Menu

Python lambda:匿名函数、排序 key 与 map/filter

lambda 是什么、适合做什么,以及它真正派得上用场的少数几个地方,还有什么时候应该改用有名字的函数。

本页包含可运行的编辑器。编辑、运行,立即查看输出。

懒得起名字的函数

Python 中的大多数函数都用 def 定义,有名字,放在文件里以便复用。lambda 是一种更小、没有名字的替代写法,在少数几种场合下,定义一个完整的函数显得过于繁琐,这时它就派上用场了。

两种写法并排对比:

两个函数做的事情完全一样。lambda 版本写在一行里,因为这基本上就是它的使命:为一次性的场景准备的一次性函数。

语法

lambda <params>: <expression>

  • <params> 和 def 使用的参数列表一样,支持默认值、*args 和 **kwargs。
  • <expression> 是单个表达式,它的值就是返回值。

示例:

没有 return 关键字,表达式的值会被隐式返回。

唯一的限制

lambda 只能包含一个表达式,不能在里面放语句:

但你可以使用三元表达式:

如果你需要不止一个表达式,那就是该换成 def 的信号了。

lambda 真正派得上用场的地方

把 lambda 赋值给一个变量,几乎总是不如一个有名字的 def:

这完全不如 def double(x): return x * 2:可读性一样,而且 lambda 版本在调用栈信息中只会给调试器一个毫无帮助的名字 <lambda>。

lambda 只在一个地方大放异彩:作为内联参数传给高阶函数。

自定义排序 key

最典型的用法:

sorted 的 key 参数需要一个函数,它接收一个元素,返回用来排序的值。一行 lambda 恰到好处,为这么小的事情写一个完整的 def 会显得太重。

你可以用元组按多个字段排序:

min、max、filter、map

情况类似,它们都接受一个可选的函数参数:

对于 map 和 filter,列表推导式通常更清晰:

正因如此,大多数 Python 开发者更喜欢用推导式而不是 map/filter。而在 sorted、min 和 max 中没有推导式这样的捷径,lambda 仍然是最自然的选择。

lambda 与 operator

当你的 lambda 只是“取一个键”或“取一个属性”时,Python 的 operator 模块提供了更快、更清晰的替代方案:

优势不算大,但在已经导入了 operator 的代码中,它读起来更具声明性一些。

什么时候该换回 def

只要满足下面任意一条,就写一个 def:

  1. 逻辑无法简洁地写成一个表达式。
  2. 给函数起个名字能提高可读性。
  3. 同样的逻辑会在不止一个地方使用。
  4. 函数需要文档字符串(lambda 无法带文档字符串)。

记住:Python 不按行数打分。一旦逻辑不那么简单,一个三行的有名函数几乎总是比一行 lambda 更好读。

下一篇:装饰器

lambda 把函数当作值传来传去。装饰器把这个思路又往前推进了一步:只需在上面一行加一个 @,就能给任何函数包上可复用的行为,比如日志、计时、缓存、权限验证。这就是下一页的内容。

常见问题

Python 中的 lambda 是什么?

lambda 是一种可以写在一行里的简短匿名函数。lambda x: x * 2 等价于 def double(x): return x * 2,只是没有名字。当你需要把一个很小的函数作为参数传给另一个函数时,它最有用。

什么时候该用 lambda 而不是 def?

对于只用一次、只有一个表达式、直接传给 sorted、max 或 filter 之类函数的情况,用 lambda。只要函数体超过一个表达式,或者你想给它起个名字,就用 def。有名字的函数几乎总是更清晰。

lambda 有哪些限制?

lambda 只能包含一个表达式,不能包含语句。不能赋值,不能写 if 代码块(不过可以用三元表达式 a if cond else b),不能写多行逻辑。如果你发现自己在和这些限制较劲,就换成 def。

Coddy 编程语言插图

和 Coddy 一起学编程

开始