第 18 课 · 进阶 · 18 分钟

Python Lambda、map 与 filter

写简短函数,不写循环也能转换序列。

lambda 语法map 与 filter惰性迭代器

收银机导出一串订单,Maya 想按每杯单价排序。为一行比较专门写个具名函数,好像有点小题大做。lambda 什么时候才值得出场?

lambda 是一个小型匿名函数。map 和 filter 会把函数应用到序列上,但在 Python 3 中返回的是惰性迭代器。想查看全部结果时,先转成列表。操作很简单时,推导式往往更清楚。 你还会看到 lambda 的延迟绑定、一次性迭代器,以及用 key 代替 map 后再排序。

lambda 是短函数

lambda 参数: 表达式 可以不用 def 代码块就创建函数。它适合作为一行规则传给另一个函数。如果逻辑需要名字、多个步骤或文档字符串,就改用 def。

double = lambda n: n * 2
print(double(4))
print((lambda a, b: a + b)(2, 3))

小型匿名函数

map 转换每个元素

map(function, iterable) 会对每个元素调用一次函数。Python 3 中结果是迭代器,所以要用 list() 包起来才能打印全部值。原序列不会被修改。

nums = [1, 2, 3]
print(list(map(lambda n: n + 1, nums)))
print(nums)

惰性的 map

filter 保留匹配项

filter(predicate, iterable) 只保留谓词返回 True 的元素。谓词可以是 lambda,也可以是具名函数。打印或索引前,先把结果转成列表。

nums = [1, 2, 3, 4]
even = filter(lambda n: n % 2 == 0, nums)
print(list(even))

保留符合条件的值

lambda 在调用时才查变量

lambda 在被调用时才查找自由变量,而不是创建时。循环里创建的多个 lambda 都引用同一个 n,就都会看到最后的值。需要各自保存当前值时,用默认参数捕获。

funcs = [lambda: n for n in range(3)]
print([fn() for fn in funcs])
fixed = [lambda n=n: n for n in range(3)]
print([fn() for fn in fixed])

用默认参数绑定当前循环值

map 和 filter 只能消费一次

map() 和 filter() 返回迭代器,不是列表。消费完就耗尽。需要查看或重复使用时转成列表;不需要时,直接交给 sum() 或 any(),它们也只消费一次。

numbers = map(lambda n: n * 2, [1, 2, 3])
print(list(numbers))
print(list(numbers))
filtered = filter(lambda n: n > 1, [1, 2, 3])
print(any(filtered))
print(any(filtered))

耗尽的迭代器不会重新开始

用 key,不要先 map 再排序

只需要极值或顺序时,把 key 函数直接交给 min、max 或 sorted。单独构造一个映射列表会多一步,还可能丢掉原记录。lambda 只写一个短表达式;规则需要名字时改用 def。

orders = [("latte", 4.5), ("tea", 3.0), ("mocha", 5.0)]
cheapest = min(orders, key=lambda item: item[1])
names = sorted(orders, key=lambda item: item[1], reverse=True)
print(cheapest)
print([name for name, price in names])

保留记录,传入规则

本课要点

  • lambda 用来创建小型匿名函数。
  • map 对每个元素应用函数,并返回迭代器。
  • filter 保留谓词为真的元素。
  • 列表推导式通常比 map 或 filter 更容易读。
  • lambda 延迟绑定;迭代器只消费一次;key 函数能保留原记录。

常见错误

  • 直接打印 map 或 filter 对象,却期待看到列表。
  • 逻辑很复杂时仍然硬写 lambda,而不是用具名函数。
  • 忘记 map 和 filter 在被消费前是惰性的。
  • 对映射后的价格列表排序,结果丢掉了饮料名。
轮到你

用 map 和 filter 把 [1, 2, 3, 4, 5] 中的偶数平方。

动手试试

改改变量、先预测输出,再运行代码。第一次点击“运行代码”时会下载 Python 运行时,可能需要几秒钟。

浏览器内 Python本地运行 · 无需账号
首次运行会从 CDN 下载 Pyodide。修改后点击“运行代码”。

练习本课

12 道题,作答后立即看到解释。

查看 12 道题答案开始练习
← 嵌套数据递归 →