从入门到高级详解Python中reduce()函数的使用

 更新时间:2026年07月23日 09:20:08   作者:星河耀银海  
本文深入讲解Python reduce()函数,从基本语法到高级应用,包括聚合计算、管道处理和深度合并等技巧,告诉你何时用reduce(),何时用内置函数更高效,助你写出更优雅的函数式代码

一、开篇:从"逐个处理"到"累积计算"

map()对序列中的每个元素应用同一个操作,filter()从序列中筛选出符合条件的元素。而reduce()的思路完全不同——它将序列中的元素两两聚合,最终"累积"成一个结果。

用一个简单例子理解reduce的思维:

from functools import reduce

# 问题:计算 [1, 2, 3, 4, 5] 的累加和
numbers = [1, 2, 3, 4, 5]

# reduce的累积过程:
# 第1步:1 + 2 = 3
# 第2步:3 + 3 = 6
# 第3步:6 + 4 = 10
# 第4步:10 + 5 = 15
# 结果:15

result = reduce(lambda a, b: a + b, numbers)
print(result)  # 15

# 等价于:
# ((((1 + 2) + 3) + 4) + 5) = 15

reduce()像一个"滚雪球"的过程——从第一个元素开始,依次将累积结果与下一个元素进行计算,最终得到一个汇总值。

二、reduce()的基本用法

2.1 语法和工作原理

from functools import reduce

# reduce(function, iterable[, initializer])
# function: 二元函数,接收两个参数(累积值, 下一个元素),返回新的累积值
# iterable: 可迭代对象
# initializer: 可选,初始累积值

# 工作原理图解:
# 没有initializer时:
#   累积值 = 第一个元素
#   for 每个剩余元素:
#       累积值 = function(累积值, 当前元素)
#   return 累积值

# 有initializer时:
#   累积值 = initializer
#   for 每个元素:
#       累积值 = function(累积值, 当前元素)
#   return 累积值

# ⌨️ 逐步查看reduce的过程
numbers = [1, 2, 3, 4, 5]

def add_and_show(a, b):
    """加法并显示中间过程"""
    result = a + b
    print(f"  {a} + {b} = {result}")
    return result

print("reduce过程:")
total = reduce(add_and_show, numbers)
print(f"最终结果: {total}")
# 输出:
# reduce过程:
#   1 + 2 = 3
#   3 + 3 = 6
#   6 + 4 = 10
#   10 + 5 = 15
# 最终结果: 15

2.2 initializer(初始值)的作用

# 💡 initializer可以改变reduce的行为

numbers = [1, 2, 3, 4, 5]

# 没有initializer——从第一个元素开始
result1 = reduce(lambda a, b: a + b, numbers)
print(result1)  # 15

# 有initializer=0——从0开始
result2 = reduce(lambda a, b: a + b, numbers, 0)
print(result2)  # 15(结果相同)

# 有initializer=10——从10开始
result3 = reduce(lambda a, b: a + b, numbers, 10)
print(result3)  # 25 = 10 + (1+2+3+4+5)

# ⚠️ initializer很关键!空序列的情况
empty_list = []

# 没有initializer——报错!
# reduce(lambda a, b: a + b, empty_list)
# TypeError: reduce() of empty iterable with no initial value

# 有initializer——安全返回
result4 = reduce(lambda a, b: a + b, empty_list, 0)
print(result4)  # 0

# 💡 始终提供initializer是个好习惯——让代码更安全

三、reduce()的经典应用

3.1 聚合计算

from functools import reduce
import operator

numbers = [1, 2, 3, 4, 5]

# 累加求和
total = reduce(operator.add, numbers)
print(f"求和: {total}")  # 15

# 累乘求积
product = reduce(operator.mul, numbers)
print(f"求积: {product}")  # 120(5的阶乘)

# 找最大值
maximum = reduce(lambda a, b: a if a > b else b, numbers)
print(f"最大值: {maximum}")  # 5

# 找最小值
minimum = reduce(lambda a, b: a if a < b else b, numbers)
print(f"最小值: {minimum}")  # 1

# 字符串拼接
words = ["Python", "是", "一门", "优雅的", "语言"]
sentence = reduce(lambda a, b: a + b, words)
print(sentence)  # Python是一门优雅的语言

# 使用空格分隔的拼接
sentence2 = reduce(lambda a, b: f"{a} {b}", words)
print(sentence2)  # Python 是 一门 优雅的 语言

3.2 实现阶乘和其他数学运算

from functools import reduce
import operator

# 阶乘 n! = 1 × 2 × 3 × ... × n
def factorial(n):
    """计算n的阶乘"""
    if n < 0:
        raise ValueError("阶乘只对非负整数定义")
    if n == 0:
        return 1
    return reduce(operator.mul, range(1, n + 1))

for n in range(11):
    print(f"{n}! = {factorial(n)}")
# 0! = 1
# 1! = 1
# 2! = 2
# ...
# 10! = 3628800

# 最大公约数(GCD)
import math
def gcd_of_list(numbers):
    """计算列表中所有数的最大公约数"""
    if not numbers:
        raise ValueError("列表不能为空")
    return reduce(math.gcd, numbers)

print(gcd_of_list([48, 64, 96]))    # 16
print(gcd_of_list([100, 75, 25]))   # 25
print(gcd_of_list([17, 31]))        # 1(互质)

# 最小公倍数(LCM)
def lcm_of_list(numbers):
    """计算列表中所有数的最小公倍数"""
    if not numbers:
        raise ValueError("列表不能为空")
    return reduce(math.lcm, numbers)  # Python 3.9+

print(lcm_of_list([4, 6, 8]))   # 24

3.3 用reduce()实现map()和filter()

from functools import reduce

# 💡 reduce可以模拟map
def my_map(func, iterable):
    """用reduce实现map"""
    return reduce(
        lambda acc, item: acc + [func(item)],
        iterable,
        []  # 初始值:空列表
    )

result = my_map(lambda x: x ** 2, [1, 2, 3, 4, 5])
print(result)  # [1, 4, 9, 16, 25]

# 💡 reduce可以模拟filter
def my_filter(func, iterable):
    """用reduce实现filter"""
    return reduce(
        lambda acc, item: acc + [item] if func(item) else acc,
        iterable,
        []
    )

result = my_filter(lambda x: x % 2 == 0, range(1, 11))
print(result)  # [2, 4, 6, 8, 10]

# ⚠️ 但实际开发中不要这样用——直接用map()和filter()或列表推导式
# 这只是用来帮助理解reduce的能力

四、reduce()的高级应用

4.1 管道/流水线处理

from functools import reduce

# 定义一系列数据处理函数
def remove_none(data):
    """移除None值"""
    return [x for x in data if x is not None]

def convert_to_int(data):
    """转为整数"""
    return [int(x) for x in data]

def filter_positive(data):
    """只保留正数"""
    return [x for x in data if x > 0]

def multiply_by(data, factor):
    """乘以因子"""
    return [x * factor for x in data]

# 用reduce链式应用这些处理
pipeline = [
    remove_none,
    convert_to_int,
    filter_positive,
    lambda data: multiply_by(data, 2),
]

raw_data = ["1", None, "3", "-2", "5", None, "0", "8"]
result = reduce(lambda data, step: step(data), pipeline, raw_data)
print(result)  # [2, 6, 10, 16]

# 解释:data经过pipeline的每一层转换
# raw_data = ["1", None, "3", "-2", "5", None, "0", "8"]
# → remove_none: ["1", "3", "-2", "5", "0", "8"]
# → convert_to_int: [1, 3, -2, 5, 0, 8]
# → filter_positive: [1, 3, 5, 8]
# → multiply_by(×2): [2, 6, 10, 16]

4.2 深度合并字典

from functools import reduce

# 合并多个字典(后面的覆盖前面的)
dicts = [
    {"host": "localhost", "port": 8080},
    {"port": 9090, "debug": True},           # port覆盖前面的
    {"timeout": 30, "retries": 3},
]

merged = reduce(lambda a, b: {**a, **b}, dicts)
print(merged)
# {'host': 'localhost', 'port': 9090, 'debug': True, 'timeout': 30, 'retries': 3}

# 深度合并(嵌套字典也合并)
configs = [
    {"database": {"host": "localhost", "port": 5432}, "debug": False},
    {"database": {"port": 5433, "name": "mydb"}, "cache": True},
    {"debug": True, "timeout": 30},
]

def deep_merge(a, b):
    """深度合并两个字典"""
    result = dict(a)
    for key, value in b.items():
        if key in result and isinstance(result[key], dict) and isinstance(value, dict):
            result[key] = deep_merge(result[key], value)
        else:
            result[key] = value
    return result

final_config = reduce(deep_merge, configs, {})
print(final_config)
# {'database': {'host': 'localhost', 'port': 5433, 'name': 'mydb'},
#  'debug': True, 'cache': True, 'timeout': 30}

五、reduce() vs 其他方式

from functools import reduce
import operator

# reduce vs 内置函数(能用内置就用内置)
numbers = [1, 2, 3, 4, 5]

# reduce求和
total1 = reduce(operator.add, numbers)  # 15
# 内置sum()求和——更好
total2 = sum(numbers)  # 15

# reduce求积
product1 = reduce(operator.mul, numbers)  # 120
# Python 3.8+ math.prod()——更好
import math
product2 = math.prod(numbers)  # 120

# reduce找最值
max1 = reduce(lambda a, b: a if a > b else b, numbers)  # 5
max2 = max(numbers)  # 5 —— 更好

# reduce拼接字符串
words = ["a", "b", "c"]
concat1 = reduce(lambda a, b: a + b, words)  # "abc"
concat2 = "".join(words)  # "abc" —— 更好

# 💡 经验法则:
# - 有内置函数 → 用内置函数
# - 简单聚合 → 用内置函数或for循环
# - 复杂聚合逻辑 → reduce()
# - reduce让代码变难读 → 用for循环重写

六、总结

reduce()是函数式编程三件套中最后一个。它不像map()filter()那么常用,但在需要"累积计算"的场景中,它比其他方式更自然。

核心要点:

  1. reduce(func, iterable, [initial])将序列累积为单个值
  2. 始终提供initializer——避免空序列报错
  3. 能用内置函数就用内置——sum()max()math.prod()比reduce更清晰也更高效
  4. reduce模拟map/filter仅作学习用途——实际不要用
  5. 管道处理是reduce的亮点场景——在函数式数据流中非常有用

reduce的精髓:当你需要把一组数据"折叠"成一个结果时,想到它。

到此这篇关于从入门到高级详解Python中reduce()函数的使用的文章就介绍到这了,更多相关Python reduce()用法内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 使用Pytorch构建第一个神经网络模型 附案例实战

    使用Pytorch构建第一个神经网络模型 附案例实战

    这篇文章主要介绍了用Pytorch构建第一个神经网络模型(附案例实战),本文通过实例代码给大家讲解的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-03-03
  • python中sort和sorted排序的实例方法

    python中sort和sorted排序的实例方法

    在本篇文章中小编给大家带来的是关于python中sort和sorted排序的实例方法以及相关知识点,有需要的朋友们可以学习下。
    2019-08-08
  • Python之is与==的区别详解

    Python之is与==的区别详解

    这篇文章主要介绍了Python之is与==的区别详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-09-09
  • PyQt5事件处理之定时在控件上显示信息的代码

    PyQt5事件处理之定时在控件上显示信息的代码

    这篇文章主要介绍了PyQt5事件处理之定时在控件上显示信息的代码,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-03-03
  • Python 使用 pip 安装 matplotlib 模块的方法

    Python 使用 pip 安装 matplotlib 模块的方法

    matplotlib是python中强大的画图模块,这篇文章主要介绍了Python 使用 pip 安装 matplotlib 模块(秒解版),本文给大家介绍的非常详细,需要的朋友可以参考下
    2023-02-02
  • Python socket.error: [Errno 98] Address already in use的原因和解决方法

    Python socket.error: [Errno 98] Address already in use的原因和解决

    这篇文章主要介绍了Python socket.error: [Errno 98] Address already in use的原因和解决方法,在Python的socket编程中可能会经常遇到这个问题,需要的朋友可以参考下
    2014-08-08
  • Python3读写ini配置文件的示例

    Python3读写ini配置文件的示例

    这篇文章主要介绍了Python3读写ini配置文件的示例,帮助大家更好的理解和使用python,感兴趣的朋友可以了解下
    2020-11-11
  • Python源码中明文账密的扫描、拦截与加密处理实例代码

    Python源码中明文账密的扫描、拦截与加密处理实例代码

    在现代互联网时代,数据的安全性是至关重要的,为了保护数据的完整性和保密性,人们通常会对敏感数据进行加密,这篇文章主要介绍了Python源码中明文账密的扫描、拦截与加密处理的相关资料,需要的朋友可以参考下
    2026-03-03
  • Python中不可变数据类型int, float, str, bool详解

    Python中不可变数据类型int, float, str, bool详解

    这篇文章深入浅出解析Python中int、str、float、bool等不可变数据类型的核心特性,帮你理解对象标识、值比较与内存缓存机制,并对比可变类型,让你的代码更安全高效,需要的朋友可以参考下
    2026-07-07
  • Python类的绑定方法和非绑定方法实例解析

    Python类的绑定方法和非绑定方法实例解析

    这篇文章主要介绍了Python类的绑定方法和非绑定方法实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-03-03

最新评论