懒得起名字的函数
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:
- 逻辑无法简洁地写成一个表达式。
- 给函数起个名字能提高可读性。
- 同样的逻辑会在不止一个地方使用。
- 函数需要文档字符串(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。