递归与匿名函数
本教程共 70 篇 · 第 23 篇 · 更新于 2026-07-22 · 约 3 分钟阅读
23. 递归与匿名函数
本节目标:理解递归的思想,掌握 lambda 表达式,学会配合 map/filter 使用。
递归函数
函数内部调用自己,就是递归。经典例子是阶乘:
def factorial(n):
if n == 1:
return 1
return n * factorial(n - 1)
print(factorial(5)) # 120
执行过程:
factorial(5)
=> 5 * factorial(4)
=> 5 * (4 * factorial(3))
=> 5 * (4 * (3 * factorial(2)))
=> 5 * (4 * (3 * (2 * factorial(1))))
=> 5 * (4 * (3 * (2 * 1)))
=> 120
Note递归必须有一个终止条件(base case),不然会无限递归直到栈溢出。
递归的另一个经典例子:斐波那契数列
def fib(n):
if n <= 1:
return n
return fib(n - 1) + fib(n - 2)
print(fib(10)) # 55
Warning上面的
fib有大量重复计算,fib(30)就已经很慢了。实际项目里用循环或缓存(后面会讲 lru_cache)。
递归深度限制
Python 默认递归深度限制是 1000:
>>> import sys
>>> sys.getrecursionlimit()
1000
超过会报错 RecursionError。能写循环解决的问题,优先用循环。递归更适合处理树形结构、分治算法等天然递归的问题。
lambda 表达式
lambda 是创建匿名函数的快捷方式,语法只有一行:
lambda 参数: 表达式
# 普通函数
def add(x, y):
return x + y
# 等价的 lambda
add = lambda x, y: x + y
print(add(2, 3)) # 5
Tiplambda 不是来替代
def的。它适合写简单的、一次性使用的小函数。复杂逻辑还是用def,可读性更好。
lambda 配合 map()
map() 对可迭代对象的每个元素执行函数:
nums = [1, 2, 3, 4, 5]
# 传统写法
squares = []
for n in nums:
squares.append(n ** 2)
# map + lambda
squares = list(map(lambda x: x ** 2, nums))
# [1, 4, 9, 16, 25]
Note对于简单操作,列表推导式通常更清晰:
[x**2 for x in nums]。map 在函数已经存在、或者处理大量数据时更有优势。
lambda 配合 filter()
filter() 按条件筛选元素:
nums = [1, 2, 3, 4, 5, 6]
evens = list(filter(lambda x: x % 2 == 0, nums))
# [2, 4, 6]
# 等价推导式
[x for x in nums if x % 2 == 0]
lambda 配合 sorted()
sorted() 的 key 参数指定排序依据:
students = [
{"name": "Alice", "score": 85},
{"name": "Bob", "score": 92},
{"name": "Charlie", "score": 78},
]
# 按分数排序
sorted_by_score = sorted(students, key=lambda s: s["score"])
# [{'name': 'Charlie', 'score': 78}, {'name': 'Alice', 'score': 85}, {'name': 'Bob', 'score': 92}]
# 按分数降序
sorted_by_score = sorted(students, key=lambda s: s["score"], reverse=True)
Tip
key参数非常强大。按字符串长度排序:sorted(words, key=len);按绝对值排序:sorted(nums, key=abs)。
reduce()
reduce() 把序列两两合并成一个值:
from functools import reduce
nums = [1, 2, 3, 4, 5]
product = reduce(lambda x, y: x * y, nums)
print(product) # 120,即 1*2*3*4*5
Note
reduce从 Python 3 起移到了functools模块。 Guido 认为它可读性不好,多数场景可以用循环或sum()替代。了解即可,不必滥用。
来源:参考了 runoob「Python lambda」、liaoxuefeng「递归函数」等,改写后所得。