跳到主要内容

Lambda 与短小可调用对象

Lambda 表达式用于创建仅包含单个表达式的匿名函数:

by_last_name = lambda person: person.last_name.casefold()
people.sort(key=by_last_name)

它的最佳用途是作为直接传递给 API 的简短可调用对象,尤其是 key= 参数。如果逻辑需要文档字符串(docstring)、类型注解、复用、多步骤处理,或者需要更有意义的错误堆栈,具名函数会更清晰。

records.sort(key=lambda row: (row.priority, row.created_at))

对于常规的转换和过滤,优先使用列表推导式或生成器表达式:

active_names = [user.name for user in users if user.active]
total = sum(order.amount for order in orders)

相比嵌套 mapfilter 和 lambda,推导式通常能更直观地表达意图。只有当已有一个具名函数能准确表达操作时,map 才更有用武之地。

闭包陷阱

函数捕获的是变量名,而非变量值,变量的值在函数执行时才被查找。因此,在循环中创建回调函数时容易踩中“晚绑定”陷阱:

callbacks = [lambda: index for index in range(3)]
# 每个回调都返回 2。

如果需要捕获循环当前的值,应显式通过默认参数捕获:

callbacks = [lambda index=index: index for index in range(3)]

默认参数在函数创建时求值。对于逻辑稍复杂的回调,使用小型工厂函数或 functools.partial 往往比 lambda 更易读、更易解释。

不要将 lambda 语法等同于函数式编程中的“纯函数”。Lambda 和具名函数一样,完全可以调用有状态函数或修改对象。

参考

探索关联

这篇笔记还没有文档关联。

同主题的其他笔记 (46)

打开关联网络