【Python】基础语法入门(十八)——函数式编程初探:用 `map`、`filter`、`reduce` 和 `lambda` 写出更简洁的代码


🧩 说明 :虽然 Python 是多范式语言,但其对函数式编程(Functional Programming) 的支持能让你在处理数据时写出更简洁、声明式的代码。本篇聚焦四个核心工具:lambdamap()filter()functools.reduce(),助你告别冗长循环,提升代码表达力。

你将学会:

  • 什么是匿名函数(lambda)?
  • 如何用 map 批量转换数据?
  • 如何用 filter 精准筛选元素?
  • reduce 如何将序列"折叠"为单值?
  • 何时该用函数式风格?何时该用列表推导式?

1. 函数式编程思想简介

核心理念

  • 函数是一等公民(可赋值、传参、返回)
  • 避免改变状态和可变数据(强调不可变性
  • 表达式 代替语句

💡 Python 并非纯函数式语言,但合理使用函数式工具能让代码更清晰。


2. lambda:匿名函数

用于定义简单、一次性的小函数。

语法

python 复制代码
lambda 参数: 表达式

示例对比

python 复制代码
# 普通函数
def square(x):
    return x ** 2

# lambda 等价写法
square = lambda x: x ** 2

# 直接使用(常见于高阶函数)
numbers = [1, 2, 3, 4]
squared = list(map(lambda x: x**2, numbers))
print(squared)  # [1, 4, 9, 16]

适用场景

  • 作为 map/filter/sorted 的参数

  • 简单逻辑(一行能写完)
    不适用场景

  • 复杂逻辑(应使用普通函数 + 文档字符串)


3. map():批量应用函数

将函数映射到序列的每个元素,返回迭代器。

基本用法

python 复制代码
# 将字符串转为整数
str_nums = ["1", "2", "3"]
int_nums = list(map(int, str_nums))
print(int_nums)  # [1, 2, 3]

# 自定义函数
def to_upper(s):
    return s.upper()

words = ["hello", "world"]
upper_words = list(map(to_upper, words))
# 或用 lambda
upper_words = list(map(lambda s: s.upper(), words))

多序列支持

python 复制代码
# 同时处理两个列表
list1 = [1, 2, 3]
list2 = [10, 20, 30]
result = list(map(lambda x, y: x + y, list1, list2))
print(result)  # [11, 22, 33]

⚠️ 注意:map 返回迭代器 ,需用 list() 转换才能重复使用。


4. filter():按条件筛选

保留使函数返回 True 的元素。

示例

python 复制代码
# 筛选偶数
numbers = [1, 2, 3, 4, 5, 6]
evens = list(filter(lambda x: x % 2 == 0, numbers))
print(evens)  # [2, 4, 6]

# 筛选非空字符串
texts = ["apple", "", "banana", " ", "cherry"]
non_empty = list(filter(lambda s: s.strip(), texts))
print(non_empty)  # ['apple', 'banana', 'cherry']

🔍 filter 也返回迭代器。


5. functools.reduce():累积计算

将序列"折叠"为单个值(需从 functools 导入)。

基本原理

python 复制代码
from functools import reduce

# 计算累加:((1+2)+3)+4
numbers = [1, 2, 3, 4]
total = reduce(lambda acc, x: acc + x, numbers)
print(total)  # 10

# 初始值可选
product = reduce(lambda acc, x: acc * x, [1, 2, 3, 4], 1)
print(product)  # 24

实用场景

  • 求最大值(虽有 max(),但演示逻辑)
  • 连接字符串
  • 复杂累积逻辑
python 复制代码
# 连接单词
words = ["Hello", "World", "Python"]
sentence = reduce(lambda a, b: a + " " + b, words)
print(sentence)  # Hello World Python

⚠️ 注意 :简单操作(如求和、求积)优先用内置函数 sum()math.prod()


6. 函数式 vs 列表推导式:如何选择?

特性 函数式(map/filter 列表推导式
可读性 适合简单函数 更直观(Pythonic)
性能 略快(C 实现) 接近
灵活性 支持任意函数 仅表达式
内存 返回迭代器(省内存) 直接生成列表

对比示例

python 复制代码
nums = range(10)

# 函数式
result1 = list(map(lambda x: x**2, filter(lambda x: x % 2 == 0, nums)))

# 列表推导式(推荐!)
result2 = [x**2 for x in nums if x % 2 == 0]

# 两者结果相同
assert result1 == result2

社区共识

"在 Python 中,列表推导式通常比 map + filter 更清晰。"

------《流畅的 Python》(Fluent Python)
📌 建议

  • 简单过滤/转换 → 用列表推导式
  • 已有命名函数 → 可用 map(func, iterable)
  • 复杂累积 → 考虑 reduce 或普通循环

7. 高级技巧:组合使用

示例:处理学生成绩

python 复制代码
students = [
    {"name": "Alice", "score": 85},
    {"name": "Bob", "score": 92},
    {"name": "Charlie", "score": 78}
]

# 获取及格学生姓名(>=80),按分数降序
from operator import itemgetter

passed_names = list(map(
    lambda s: s["name"],
    filter(lambda s: s["score"] >= 80, students)
))
# 但更 Pythonic 的写法:
passed_names = [s["name"] for s in students if s["score"] >= 80]
passed_names.sort(key=lambda name: next(s["score"] for s in students if s["name"] == name), reverse=True)

💡 提示:对于字典排序,可用 operator.itemgetter 提升可读性:

python 复制代码
from operator import itemgetter
top_students = sorted(students, key=itemgetter("score"), reverse=True)

8. 常见陷阱与注意事项

问题 解决方案
忘记 list() 转换 map/filter 返回迭代器,只能遍历一次
lambda 过于复杂 改用普通函数
在循环中创建 lambda 注意闭包变量绑定问题
滥用 reduce 优先考虑 sumanyall 等内置函数

闭包陷阱示例(避免!)

python 复制代码
# 错误:所有 lambda 共享同一个 i
funcs = []
for i in range(3):
    funcs.append(lambda: i)  # 所有返回 2!

# 正确:通过默认参数捕获当前值
funcs = []
for i in range(3):
    funcs.append(lambda x=i: x)

9. 总结:何时使用函数式工具?

场景 推荐方式
简单数据转换 + 过滤 ✅ 列表推导式 [x*2 for x in nums if x>0]
已有命名函数应用 map(my_func, data)
复杂累积逻辑 ⚠️ 谨慎使用 reduce,或用普通循环
需要惰性求值(大数据) map/filter(返回迭代器)

🐍 核心原则
"代码是写给人看的,其次才是机器。"

选择最清晰、最易维护的写法,而非最"函数式"的写法。


下一步练习

  1. mapfilter 重写你的 To-Do List 中的"筛选已完成任务"功能
  2. 编写一个函数,用 reduce 计算列表中所有正数的乘积
  3. 对比以下三种写法的可读性:
    • map + filter
    • 列表推导式
    • 普通 for 循环

掌握函数式思维,不是为了炫技,而是多一种优雅表达逻辑的方式。

继续精进,写出既简洁又清晰的 Python 代码!

相关推荐
m5655bj2 小时前
如何使用 Python 调整 PDF 页面顺序?
python·pdf
LiYingL2 小时前
SwarmAgentic:利用蜂群智能全自动生成代理系统
人工智能
数据科学项目实践2 小时前
建模步骤 3 :数据探索(EDA) — 1、初步了解数据:自定义函数
大数据·人工智能·python·机器学习·matplotlib·数据可视化
qq_406176142 小时前
JavaScript中的循环特点和区别
开发语言·javascript·ecmascript
我命由我123452 小时前
Python 开发 - OpenAI 兼容阿里云百炼平台 API
开发语言·人工智能·后端·python·阿里云·ai·语言模型
iReachers2 小时前
极速AI助手如何使用免费的阿里云的大模型
人工智能·阿里云·云计算
GokuCode2 小时前
【GO高级编程】02.GO接收者概述
开发语言·后端·golang
行云流水20192 小时前
青少年编程考试时间汇总:考级与竞赛的不同节点
人工智能·青少年编程