一、什么是 reduce?
reduce() 是 Python 中一个非常有用的高阶函数,它用于对可迭代对象中的元素进行累积计算,最终得到一个单一的值。简单来说,reduce 会反复地将一个二元操作函数应用到序列的元素上,将序列“缩减”为一个值。
例如,计算一个列表所有元素的和,可以这样理解:reduce 先把前两个元素相加,得到结果再与第三个元素相加,以此类推,直到处理完所有元素。
from functools import reduce
numbers = [1, 2, 3, 4, 5]
result = reduce(lambda x, y: x + y, numbers)
print(result) # 15
二、为什么需要 reduce?
虽然很多累积操作可以用循环实现,但 reduce 提供了一种更声明式的写法,代码更简洁,尤其在处理复杂累积逻辑时。它也是函数式编程的重要工具之一。
三、reduce 的语法
from functools import reduce
reduce(function, iterable[, initializer])
- • function:一个接收两个参数的函数,用于指定如何将两个元素合并。
- • iterable:一个可迭代对象(如列表、元组等)。
- • initializer(可选):初始值。如果提供,它会被放在序列之前参与第一次计算;如果序列为空,则返回该初始值。
返回值:一个值,即最终的累积结果。
四、reduce 的工作过程
假设有一个列表 [a, b, c, d],使用 reduce(function, [a, b, c, d]),过程如下:
- 1. 先用
function(a, b) 得到结果 r1。 - 2. 再用
function(r1, c) 得到结果 r2。 - 3. 再用
function(r2, d) 得到结果 r3。
如果提供了初始值 init,则过程为:function(init, a) → r1,然后 function(r1, b) → ... 最后返回结果。
五、基本示例
5.1 求和
from functools import reduce
numbers = [10, 20, 30, 40]
total = reduce(lambda x, y: x + y, numbers)
print(total) # 100
5.2 求积
numbers = [1, 2, 3, 4, 5]
product = reduce(lambda x, y: x * y, numbers)
print(product) # 120
5.3 使用初始值
numbers = [1, 2, 3]
# 提供初始值 100,相当于 100 + 1 + 2 + 3
total = reduce(lambda x, y: x + y, numbers, 100)
print(total) # 106
# 如果序列为空,初始值作为返回值
empty = []
result = reduce(lambda x, y: x + y, empty, 0)
print(result) # 0
六、reduce 的进阶用法
6.1 找最大值
numbers = [45, 12, 89, 33, 72]
max_value = reduce(lambda x, y: x if x > y else y, numbers)
print(max_value) # 89
6.2 字符串拼接
words = ["Hello", " ", "World", "!"]
sentence = reduce(lambda x, y: x + y, words)
print(sentence) # Hello World!
6.3 构建字典
pairs = [("a", 1), ("b", 2), ("c", 3)]
dict_result = reduce(lambda d, pair: {**d, pair[0]: pair[1]}, pairs, {})
print(dict_result) # {'a': 1, 'b': 2, 'c': 3}
6.4 计算阶乘
n = 5
factorial = reduce(lambda x, y: x * y, range(1, n+1))
print(factorial) # 120
七、reduce 与循环的对比
假设我们要计算列表中所有元素的乘积,用循环写:
product = 1
for x in numbers:
product *= x
用 reduce 写:
product = reduce(lambda x, y: x * y, numbers, 1)
两者功能相同,但 reduce 将过程抽象为“累积”的概念,代码更紧凑。不过对于简单累加,Python 内置的 sum() 更直接。
八、reduce 与 map、filter 的组合
reduce 常与 map 和 filter 结合,实现更复杂的数据处理流水线。
示例:先过滤出偶数,再求它们的平方和
numbers = [1, 2, 3, 4, 5, 6]
# 过滤出偶数,再求平方,最后求和
result = reduce(
lambda x, y: x + y,
map(lambda x: x**2, filter(lambda x: x % 2 == 0, numbers))
)
print(result) # 2²+4²+6² = 4+16+36 = 56
虽然可读性可能不如列表推导式,但展示了函数式编程的组合能力。
九、实战案例
9.1 计算列表中的最大值和最小值(同时返回)
defmin_max(acc, x):
current_min, current_max = acc
return (min(current_min, x), max(current_max, x))
numbers = [23, 45, 12, 67, 34, 89, 5]
initial = (numbers[0], numbers[0])
result = reduce(min_max, numbers, initial)
print(f"最小值:{result[0]},最大值:{result[1]}")
9.2 将多个字典合并为一个
dicts = [{"a": 1}, {"b": 2}, {"c": 3}, {"a": 4}]
# 注意:后面的同名键会覆盖前面的
merged = reduce(lambda d1, d2: {**d1, **d2}, dicts, {})
print(merged) # {'a': 4, 'b': 2, 'c': 3}
9.3 计算列表中数字的累积积(并返回中间过程)
defcumulative_product(acc, x):
last = acc[-1] if acc else1
acc.append(last * x)
return acc
numbers = [2, 3, 4]
products = reduce(cumulative_product, numbers, [1])
print(products) # [1, 2, 6, 24] (从初始值1开始累积)
9.4 统计字符串中每个字符的出现次数
text = "hello world"
char_count = reduce(
lambda acc, ch: {**acc, ch: acc.get(ch, 0) + 1},
text,
{}
)
print(char_count)
# {'h': 1, 'e': 1, 'l': 3, 'o': 2, ' ': 1, 'w': 1, 'r': 1, 'd': 1}
十、注意事项
- 1. reduce 在 Python 3 中被移到 functools 模块,使用前需要导入
from functools import reduce。 - 2. function 必须接收两个参数,并返回一个值,作为下一次调用的第一个参数。
- 3. 如果序列为空且未提供初始值,会引发
TypeError。建议提供初始值以避免空序列问题。 - 4. 性能考虑:对于简单的累加,内置函数如
sum()、max()、min() 通常更快、更清晰。 - 5. 可读性:复杂的
reduce 操作可能难以理解,此时使用循环可能更合适。 - • 如果序列只有一个元素且提供了初始值,函数会被调用一次(用初始值和该元素)。
- • 如果序列只有一个元素且未提供初始值,则直接返回该元素,函数不会被调用。
十一、reduce 与内置函数的关系
很多常用的累积操作都有专门的 built-in 函数,应优先使用它们,代码更清晰:
| | |
| sum(iterable) | reduce(lambda x,y: x+y, iterable, 0) |
| 无内置,可用 math.prod() (3.8+) | reduce(lambda x,y: x*y, iterable, 1) |
| max(iterable) | reduce(lambda x,y: x if x>y else y, iterable) |
| min(iterable) | reduce(lambda x,y: x if x<y else y, iterable) |
| all(iterable) | reduce(lambda x,y: x and y, iterable, True) |
| any(iterable) | reduce(lambda x,y: x or y, iterable, False) |
十二、总结
| |
| |
| reduce(function, iterable[, initializer]) |
| |
| |
| |
| |
reduce 是函数式编程的重要工具,掌握它能让你在处理累积数据时多一种选择。但也要注意适度使用,避免写出晦涩的代码。希望本文能帮助你理解并灵活运用 reduce。