【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 代码!

相关推荐
聆风吟º4 小时前
CANN runtime 实战指南:异构计算场景中运行时组件的部署、调优与扩展技巧
人工智能·神经网络·cann·异构计算
寻星探路5 小时前
【深度长文】万字攻克网络原理:从 HTTP 报文解构到 HTTPS 终极加密逻辑
java·开发语言·网络·python·http·ai·https
Codebee6 小时前
能力中心 (Agent SkillCenter):开启AI技能管理新时代
人工智能
lly2024066 小时前
Bootstrap 警告框
开发语言
2601_949146537 小时前
C语言语音通知接口接入教程:如何使用C语言直接调用语音预警API
c语言·开发语言
曹牧7 小时前
Spring Boot:如何测试Java Controller中的POST请求?
java·开发语言
聆风吟º7 小时前
CANN runtime 全链路拆解:AI 异构计算运行时的任务管理与功能适配技术路径
人工智能·深度学习·神经网络·cann
KYGALYX7 小时前
服务异步通信
开发语言·后端·微服务·ruby
uesowys7 小时前
Apache Spark算法开发指导-One-vs-Rest classifier
人工智能·算法·spark
AI_56787 小时前
AWS EC2新手入门:6步带你从零启动实例
大数据·数据库·人工智能·机器学习·aws