lambda 表达式
约 1247 字大约 4 分钟
2026-05-27
lambda 用来写 匿名的单表达式函数。它不会带来新的计算能力,只是在需要 "随手传一个小函数" 时少写一个 def 名字
基本语法
lambda 与 def 等价
# lambda 参数1, 参数2, ...: 表达式
def add(x: int, y: int) -> int:
return x + y
add_lambda = lambda x, y: x + y
print(add(2, 3))
print(add_lambda(2, 3))
print((lambda: 42)())
print((lambda x: "奇" if x % 2 else "偶")(3))约束:
- 函数体只能是 一个表达式,不能写语句(
if块、for块、return等) - 表达式的值就是返回值,无需
return - 可以有任意个参数,也可以没有参数:
lambda: 42
条件逻辑可以塞进条件表达式,但一复杂就该换 def
和 def 怎么选
| 维度 | lambda | def |
|---|---|---|
| 名字 | 通常匿名 | 有名字,利于栈追踪 |
| 函数体 | 单表达式 | 多语句、注释、文档 |
| 返回 | 自动 | 显式 return |
| 场景 | 回调、key=、短映射 | 复用逻辑、复杂分支 |
原则:只用一次且一眼能看懂 → lambda;需要复用、调试、类型标注完整文档 → def
PEP 8 也不鼓励 f = lambda x: ... 这种 "给 lambda 起名再当函数用" 的写法,有名字就写 def
高阶函数场景
高阶函数接收函数作参数。这是 lambda 最高频的落点
map:映射
map 与 lambda
numbers = [1, 2, 3, 4, 5]
print(list(map(lambda x: x ** 2, numbers))) # [1, 4, 9, 16, 25]
names = ["Alice", "Bob", "Charlie"]
print(list(map(lambda s: len(s), names))) # [5, 3, 7]
a, b = [1, 2, 3], [10, 20, 30]
print(list(map(lambda x, y: x + y, a, b))) # [11, 22, 33]map 返回迭代器,需要列表时再 list(...)。很多情况下列表推导更直白:
列表推导对照
numbers = [1, 2, 3, 4, 5]
print([x ** 2 for x in numbers])filter:过滤
filter 与 lambda
numbers = [1, 2, 3, 4, 5, 6]
print(list(filter(lambda x: x % 2 == 0, numbers))) # [2, 4, 6]
words = ["cat", "elephant", "dog", "butterfly"]
print(list(filter(lambda s: len(s) > 3, words)))等价推导:[x for x in numbers if x % 2 == 0]
sorted / list.sort:按 key 排序
sorted 的 key
words = ["banana", "pie", "Washington", "book"]
print(sorted(words, key=lambda s: len(s)))
print(sorted(words, key=lambda s: s[-1]))
print(sorted(words, key=lambda s: len(s), reverse=True))
nums = [-5, 2, -8, 1, -9]
print(sorted(nums, key=lambda x: abs(x)))key 接收 "从元素算出排序依据" 的函数,只算一次依据再比大小,比自己写 comparator 更符合 Python 习惯
max / min
max / min 的 key
words = ["apple", "banana", "cherry"]
print(max(words, key=lambda s: len(s))) # banana
print(min(words, key=lambda s: len(s)))
students = [
{"name": "Alice", "score": 85},
{"name": "Bob", "score": 92},
{"name": "Charlie", "score": 78},
]
print(max(students, key=lambda s: s["score"]))functools.reduce:归约
reduce 累积
from functools import reduce
numbers = [1, 2, 3, 4, 5]
print(reduce(lambda x, y: x + y, numbers)) # 15
print(reduce(lambda x, y: x * y, numbers)) # 120
print(reduce(lambda x, y: x if x > y else y, numbers)) # 5求和 / 求积更常用内置 sum / 循环;reduce 适合没有现成内置的累积模式
闭包与默认参数绑定
lambda 一样走 LEGB。循环里延迟调用时,常需要默认参数把当前值钉住
循环变量绑定陷阱
# 错误:三个函数都看到同一个 i(循环结束后的值)
funcs_bad = [lambda: i for i in range(3)]
print([f() for f in funcs_bad]) # [2, 2, 2]
# 正确:默认参数在定义时绑定
funcs_ok = [lambda i=i: i for i in range(3)]
print([f() for f in funcs_ok]) # [0, 1, 2]functools.partial:冻结部分参数
需要 "固定部分参数、留下其余参数稍后传" 时,partial 往往比嵌套 lambda 更清晰
partial 冻结参数
from functools import partial
def power(base: int, exp: int) -> int:
return base ** exp
square = partial(power, exp=2)
cube = partial(power, exp=3)
print(square(5), cube(5)) # 25 125
# 常用于回调:把多参数函数收成单参数
def greeter(greeting: str, name: str) -> str:
return f"{greeting}, {name}"
hello = partial(greeter, "Hello")
print(hello("Alice"))operator:可替代简单 lambda
标准库 operator 提供一批与运算符对应的函数,在 key= / map 里能少写一层 lambda
operator 替代短 lambda
from operator import add, itemgetter, attrgetter, methodcaller
print(list(map(add, [1, 2, 3], [10, 20, 30])))
rows = [("b", 2), ("a", 1), ("c", 3)]
print(sorted(rows, key=itemgetter(1))) # 按第二列
print(sorted(rows, key=itemgetter(0))) # 按第一列
class User:
def __init__(self, name: str, age: int) -> None:
self.name = name
self.age = age
users = [User("Bob", 30), User("Alice", 25)]
print([u.name for u in sorted(users, key=attrgetter("age"))])
print(list(map(methodcaller("upper"), ["a", "b"])))itemgetter(1) 大致相当于 lambda r: r[1],但实现是 C 层,意图也更直白
推导式 vs map / filter
多数团队读推导式比读 map(lambda ...) 更轻松。lambda 仍适合塞进 只收 callables 的 API(如某些库的 key / callback),而不是为了 "函数式风格" 强行替代推导
三种写法对照
nums = range(-3, 4)
# map + filter + lambda
print(list(map(lambda x: x * x, filter(lambda x: x > 0, nums))))
# 推导式(通常更推荐)
print([x * x for x in nums if x > 0])
# 生成器表达式:惰性,不立刻建完整列表
gen = (x * x for x in nums if x > 0)
print(gen, list(gen))