高阶函数与函数式工具
本教程共 70 篇 · 第 27 篇 · 更新于 2026-07-22 · 约 3 分钟阅读
27. 高阶函数与函数式工具
本节目标:掌握 map、filter、reduce、sorted 和 partial 的用法,能用函数式风格编写简洁代码。
什么是高阶函数
高阶函数是指接收函数作为参数,或返回函数作为结果的函数。
Python 内置了几个常用的高阶函数,配合 lambda 或自定义函数,能让代码非常紧凑。
map()
对可迭代对象的每个元素执行同一个函数:
nums = [1, 2, 3, 4, 5]
# 传统写法
squares = []
for n in nums:
squares.append(n ** 2)
# map 写法
squares = list(map(lambda x: x ** 2, nums))
# [1, 4, 9, 16, 25]
如果有多个可迭代对象,函数接收多个参数:
a = [1, 2, 3]
b = [4, 5, 6]
result = list(map(lambda x, y: x + y, a, b))
# [5, 7, 9]
Tip简单场景下,列表推导式
[x**2 for x in nums]往往更易读。map 在函数已经定义好、或需要多序列并行处理时更有优势。
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]
filter 的函数返回「真值」时保留该元素。用 None 可以过滤掉所有假值:
values = [0, 1, "", "hello", [], [1, 2], None, True]
truthy = list(filter(None, values))
# [1, 'hello', [1, 2], True]
reduce()
把序列两两累积成一个值:
from functools import reduce
nums = [1, 2, 3, 4, 5]
# 累加
reduce(lambda x, y: x + y, nums) # 15
# 累乘
reduce(lambda x, y: x * y, nums) # 120
# 找最大值
reduce(lambda x, y: x if x > y else y, nums) # 5
reduce 还可以指定初始值:
reduce(lambda x, y: x + y, [1, 2, 3], 100)
# 106,从 100 开始累加
Note
reduce在 Python 3 中被移到functools模块。因为它往往不如显式循环好读,官方推荐谨慎使用。但某些场景(如链式运算)用它很简洁。
sorted()
排序是 Python 里最高频的操作之一。sorted() 返回新列表,不修改原数据:
nums = [3, 1, 4, 1, 5]
sorted(nums) # [1, 1, 3, 4, 5]
sorted(nums, reverse=True) # [5, 4, 3, 1, 1]
key 参数指定排序依据:
words = ["banana", "pie", "Washington", "book"]
# 按长度排序
sorted(words, key=len)
# ['pie', 'book', 'banana', 'Washington']
# 按长度降序
sorted(words, key=len, reverse=True)
# 忽略大小写排序
sorted(words, key=str.lower)
复杂对象的排序:
students = [
{"name": "Alice", "score": 85},
{"name": "Bob", "score": 92},
{"name": "Charlie", "score": 78},
]
# 按分数排序
sorted(students, key=lambda s: s["score"])
# 先按分数降序,分数相同按名字升序
sorted(students, key=lambda s: (-s["score"], s["name"]))
Tip如果列表本身不需要保留原顺序,用列表的
.sort()方法更快,因为它不需要创建新列表。
operator 模块
operator 模块提供了一些内置操作的函数版本,配合高阶函数用:
from operator import add, mul, itemgetter, attrgetter
reduce(add, [1, 2, 3, 4]) # 10
reduce(mul, [1, 2, 3, 4]) # 24
# itemgetter 替代 lambda 取字典/元组的字段
data = [("Alice", 25), ("Bob", 30), ("Charlie", 20)]
sorted(data, key=itemgetter(1)) # 按索引 1 排序
sorted(data, key=itemgetter(0)) # 按索引 0 排序
# attrgetter 取对象的属性
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
people = [Person("Alice", 25), Person("Bob", 30)]
sorted(people, key=attrgetter("age"))
Tip
itemgetter和attrgetter比等价的 lambda 快一点,而且写起来更短。性能敏感或代码风格统一时优先用它们。
functools.partial
partial 用来「冻结」函数的一部分参数,得到一个新函数:
from functools import partial
# 原函数
def power(base, exponent):
return base ** exponent
# 冻结 exponent=2,得到平方函数
square = partial(power, exponent=2)
print(square(5)) # 25
# 冻结 exponent=3,得到立方函数
cube = partial(power, exponent=3)
print(cube(3)) # 27
实际应用:给 int() 指定默认进制:
from functools import partial
bin_to_int = partial(int, base=2)
print(bin_to_int("1010")) # 10
print(bin_to_int("1111")) # 15
函数式编程风格建议
Python 不是纯函数式语言,但适当借鉴它的思想能让代码更简洁:
- 优先用内置高阶函数处理数据转换
- 用 lambda 写简单的一次性函数
- 复杂逻辑还是用
def,可读性第一 - 不要为了追求「函数式」而写出晦涩的代码
来源:参考了 runoob「Python3 内置函数」、liaoxuefeng「函数式编程」等,改写后所得。