Python lambda 匿名函数详解
前言
在 Python 中,除了用 def 定义有名字的函数,还有一种更简洁的方式来创建一次性使用的小函数——那就是 lambda 匿名函数。
很多初学者觉得 lambda 难以理解,但实际上它只是一个没有名字的、单行表达式函数。一旦掌握,你会发现它在代码中非常实用:
- 排序时指定自定义规则
- 配合
map、filter快速处理数据 - 作为回调函数传入 GUI 或异步框架
- 在
pandas等数据分析库中做列操作
本文将从语法到实战,全面讲解 Python lambda 的用法。
1. lambda 基本语法
1.1 语法格式
lambda 参数1, 参数2, ... : 表达式lambda关键字声明这是一个匿名函数- 参数列表可以有多个,用逗号分隔
- 只能有一个表达式,表达式的结果就是返回值
- 不能包含语句(如
print、if语句块、for循环等)
1.2 最简单的例子
# def 写法def add(x, y): return x + y
# lambda 等价写法add = lambda x, y: x + y
print(add(3, 5)) # 8虽然可以把 lambda 赋值给变量,但 PEP 8 不推荐这样做。如果需要可复用的函数,请直接用 def。lambda 的本意是匿名、一次性使用。
1.3 多参数与无参数
# 多参数f = lambda a, b, c: a + b + cprint(f(1, 2, 3)) # 6
# 无参数import randomget_random = lambda: random.randint(1, 100)print(get_random()) # 比如 42
# 默认参数greet = lambda name, greeting="Hello": f"{greeting}, {name}!"print(greet("World")) # Hello, World!print(greet("World", "Hi")) # Hi, World!2. lambda 的常见使用场景
2.1 配合 sorted() 排序
这是 lambda 最常见的用法之一。sorted() 的 key 参数接受一个函数,lambda 正好胜任:
students = [ {"name": "Alice", "score": 85}, {"name": "Bob", "score": 92}, {"name": "Charlie", "score": 78},]
# 按 score 排序sorted_students = sorted(students, key=lambda s: s["score"])print(sorted_students)# [{'name': 'Charlie', 'score': 78}, {'name': 'Alice', 'score': 85}, {'name': 'Bob', 'score': 92}]
# 降序排列sorted_students_desc = sorted(students, key=lambda s: s["score"], reverse=True)print(sorted_students_desc)# [{'name': 'Bob', 'score': 92}, {'name': 'Alice', 'score': 85}, {'name': 'Charlie', 'score': 78}]更多排序场景:
# 按字符串长度排序words = ["apple", "banana", "kiwi", "grape"]sorted_words = sorted(words, key=lambda w: len(w))print(sorted_words) # ['kiwi', 'grape', 'apple', 'banana']
# 按元组的第二个元素排序pairs = [(1, 3), (2, 1), (4, 2)]sorted_pairs = sorted(pairs, key=lambda x: x[1])print(sorted_pairs) # [(2, 1), (4, 2), (1, 3)]
# 多条件排序(先按 score 降序,再按 name 升序)students = [ {"name": "Alice", "score": 85}, {"name": "Bob", "score": 85}, {"name": "Charlie", "score": 92},]sorted_students = sorted(students, key=lambda s: (-s["score"], s["name"]))print(sorted_students)# [{'name': 'Charlie', 'score': 92}, {'name': 'Alice', 'score': 85}, {'name': 'Bob', 'score': 85}]2.2 配合 map() 批量转换
map(func, iterable) 对可迭代对象的每个元素应用 func,返回一个迭代器:
numbers = [1, 2, 3, 4, 5]
# 每个数平方squares = list(map(lambda x: x ** 2, numbers))print(squares) # [1, 4, 9, 16, 25]
# 摄氏度转华氏度celsius = [0, 10, 20, 30, 40]fahrenheit = list(map(lambda c: c * 9/5 + 32, celsius))print(fahrenheit) # [32.0, 50.0, 68.0, 86.0, 104.0]
# 两个列表对应元素相加a = [1, 2, 3]b = [4, 5, 6]sums = list(map(lambda x, y: x + y, a, b))print(sums) # [5, 7, 9]对于简单的转换,列表推导式通常比 map + lambda 更 Pythonic:
squares = [x ** 2 for x in numbers] # 推荐squares = list(map(lambda x: x ** 2, numbers)) # 可以但不推荐2.3 配合 filter() 筛选数据
filter(func, iterable) 保留 func 返回 True 的元素:
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# 筛选偶数evens = list(filter(lambda x: x % 2 == 0, numbers))print(evens) # [2, 4, 6, 8, 10]
# 筛选长度大于 3 的字符串words = ["a", "ab", "abc", "abcd", "abcde"]long_words = list(filter(lambda w: len(w) > 3, words))print(long_words) # ['abcd', 'abcde']
# 筛选字典列表users = [ {"name": "Alice", "age": 25}, {"name": "Bob", "age": 17}, {"name": "Charlie", "age": 30},]adults = list(filter(lambda u: u["age"] >= 18, users))print(adults) # [{'name': 'Alice', 'age': 25}, {'name': 'Charlie', 'age': 30}]同样,列表推导式通常更清晰:
evens = [x for x in numbers if x % 2 == 0] # 推荐2.4 配合 reduce() 累积计算
reduce() 在 Python 3 中被移到了 functools 模块,需要显式导入:
from functools import reduce
# 累加numbers = [1, 2, 3, 4, 5]total = reduce(lambda x, y: x + y, numbers)print(total) # 15
# 阶乘n = 5factorial = reduce(lambda x, y: x * y, range(1, n + 1))print(factorial) # 120
# 找最大值numbers = [3, 7, 2, 9, 1]max_val = reduce(lambda x, y: x if x > y else y, numbers)print(max_val) # 92.5 配合 max() / min() 自定义比较
words = ["apple", "banana", "kiwi", "grape"]
# 找最长的单词longest = max(words, key=lambda w: len(w))print(longest) # banana
# 找字典列表中 score 最高的人students = [ {"name": "Alice", "score": 85}, {"name": "Bob", "score": 92}, {"name": "Charlie", "score": 78},]top_student = max(students, key=lambda s: s["score"])print(top_student) # {'name': 'Bob', 'score': 92}2.6 在 GUI 和回调中使用
import tkinter as tk
root = tk.Tk()# lambda 在 GUI 按钮回调中非常常见button = tk.Button( root, text="Click me", command=lambda: print("Button clicked!"))button.pack()root.mainloop()3. lambda 与 if-else 条件表达式
lambda 不能包含语句块,但可以使用三元条件表达式:
# 判断奇偶check = lambda x: "偶数" if x % 2 == 0 else "奇数"print(check(4)) # 偶数print(check(7)) # 奇数
# 结合 sorted 做复杂排序data = [5, -3, 2, -8, 1]# 按绝对值排序sorted_data = sorted(data, key=lambda x: abs(x))print(sorted_data) # [1, 2, -3, 5, -8]
# 多条件表达式grade = lambda score: "A" if score >= 90 else ("B" if score >= 80 else ("C" if score >= 70 else "D"))print(grade(95)) # Aprint(grade(75)) # C嵌套的三元表达式会严重降低可读性。如果条件逻辑复杂,请用 def 定义函数。
4. 立即执行 lambda(IIFE)
lambda 可以定义后立即调用(类似 JavaScript 的 IIFE):
# 定义并立即调用result = (lambda x, y: x + y)(3, 5)print(result) # 8
# 在列表推导中使用results = [(lambda x: x ** 2)(i) for i in range(5)]print(results) # [0, 1, 4, 9, 16]这种写法在 Python 中不常见,通常用普通表达式或变量代替即可。了解即可,不必刻意使用。
5. lambda 的局限性与注意事项
5.1 只能包含单个表达式
# ❌ 错误:lambda 不能包含语句# f = lambda x: print(x); return x * 2 # SyntaxError
# ✅ 正确:用 def 代替def f(x): print(x) return x * 25.2 闭包与变量捕获(常见陷阱)
这是 lambda 最经典的坑:
# ❌ 陷阱:所有 lambda 都捕获了同一个变量 ifuncs = []for i in range(3): funcs.append(lambda: i)
print([f() for f in funcs]) # [2, 2, 2] 而不是 [0, 1, 2]原因:lambda 捕获的是变量 i 本身,而不是它的值。循环结束后 i = 2,所有 lambda 引用的都是同一个 i。
解决方案:使用默认参数”冻结”当前值:
# ✅ 正确:用默认参数保存当前值funcs = []for i in range(3): funcs.append(lambda i=i: i) # i=i 创建了默认参数
print([f() for f in funcs]) # [0, 1, 2]5.3 不要在 lambda 中赋值
# ❌ 错误:lambda 中不能使用赋值语句# f = lambda x: y = x + 1 # SyntaxError
# ❌ 错误:海象运算符也不行(Python 3.8+)# f = lambda x: (y := x + 1) # SyntaxError5.4 lambda 没有类型注解
# ❌ lambda 不支持类型注解# f = lambda x: int, y: int -> int: x + y # 语法错误
# ✅ 如果需要类型注解,请用 defdef add(x: int, y: int) -> int: return x + y5.5 可读性优先
# ❌ 过度使用 lambda,难以阅读result = list(map(lambda x: x * 2, filter(lambda x: x > 0, [-3, -2, -1, 0, 1, 2, 3])))
# ✅ 用列表推导式,清晰明了result = [x * 2 for x in [-3, -2, -1, 0, 1, 2, 3] if x > 0]6. pandas 中的 lambda
在数据分析中,lambda 经常与 pandas 的 apply()、transform() 搭配:
import pandas as pd
df = pd.DataFrame({ "name": ["Alice", "Bob", "Charlie"], "score": [85, 92, 78],})
# 添加一列:评级df["grade"] = df["score"].apply(lambda x: "优秀" if x >= 90 else ("良好" if x >= 80 else "一般"))print(df)# name score grade# 0 Alice 85 良好# 1 Bob 92 优秀# 2 Charlie 78 一般
# 批量处理列名df.columns = df.columns.map(lambda c: c.upper())print(df.columns) # Index(['NAME', 'SCORE', 'GRADE'], dtype='object')7. 总结与最佳实践
| 场景 | 推荐做法 |
|---|---|
sorted() 的 key 参数 | ✅ 用 lambda |
max() / min() 的 key 参数 | ✅ 用 lambda |
简单的 map() / filter() | 优先用列表推导式 |
| 复杂的转换逻辑 | 用 def 定义函数 |
| 需要复用的函数 | 用 def,不要赋给变量 |
| 需要类型注解 | 用 def |
| 涉及多行逻辑 | 用 def |
核心原则:lambda 适合简单、一次性、作为参数传入的场景。如果函数需要复用、逻辑复杂、或需要文档说明,请用 def。
参考资料
文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!









