创建时间: 2026-08-25最后更新: 2026-08-25

1. 传入逻辑

普通函数通常接收数据,然后按照函数内部写好的步骤处理数据:

normal-function.py
1
def double(number):
2
return number * 2
3
4
print(double(3)) # 6

如果希望同一个函数可以处理不同规则,就可以把「逻辑片段」也作为参数传进去。下面的 apply_twice() 不关心具体要做什么,只负责把传入的动作执行两次:

pass-logic.py
1
def add_exclamation(text):
2
return text + "!"
3
4
def apply_twice(value, action):
5
return action(action(value))
6
7
print(apply_twice("你好", add_exclamation)) # 你好!!

这里的 action 不是一个普通数据,而是一个可以被调用的函数。apply_twice() 把执行时机和执行次数负责好,把具体逻辑交给调用方,这就是「把行为传给函数」的基本思路。

2. 函数对象

在 Python 中,函数也是对象,可以像字符串、数字一样被赋值、放进列表、作为参数传入,或者作为返回值交给其他代码:

function-value.py
1
def add(left, right):
2
return left + right
3
4
operation = add
5
operations = [add, lambda left, right: left - right]
6
7
print(operation(2, 3))
8
print(operations[0](5, 2)) # 7
9
print(operations[1](5, 2)) # 3

注意,add 和 add() 含义不同:

  • add 表示函数对象本身,可以传给另一个函数;
  • add() 表示立即调用函数,括号中的值是传入的实参。

当一个函数接收另一个函数作为参数,或者返回一个函数时,就可以称为高阶函数。高阶函数并不神秘,它只是利用了 Python「函数也是值」这一特性。

函数返回函数时,可以把一部分配置提前保存下来。这个模式也叫函数工厂:

function-factory.py
01
def make_multiplier(factor):
02
def multiply(number):
03
return number * factor
04
05
return multiply
06
07
double = make_multiplier(2)
08
triple = make_multiplier(3)
09
10
print(double(4)) # 8
11
print(triple(4)) # 12

make_multiplier() 返回了一个函数,同时这个函数记住了 factor。这正是上一节「闭包」中介绍的关系:高阶函数描述的是函数的传入或返回,闭包强调返回的函数还保存了外层变量。

3. 映射

map(function, iterable) 会把函数应用到可遍历对象的每个元素,并返回一个迭代器。需要查看全部结果时,通常使用 list() 转换:

map-basic.py
1
def to_upper(text):
2
return text.upper()
3
4
topics = ["变量", "函数", "类"]
5
result = map(to_upper, topics)
6
7
print(list(result)) # ['变量', '函数', '类']

map() 不会直接修改原列表,也不会立刻把所有结果保存成新列表。迭代器被消费后就不能再次从头读取:

map-lazy.py
1
numbers = [1, 2, 3]
2
result = map(lambda number: number * 2, numbers)
3
4
print(list(result)) # [2, 4, 6]
5
print(list(result)) # []

如果转换逻辑很简单,列表推导式通常更直观:

map-comprehension.py
1
numbers = [1, 2, 3]
2
result = [number * 2 for number in numbers]
3
4
print(result) # [2, 4, 6]

map() 适合把一个已经命名的处理函数应用到整组数据;列表推导式适合在一行中表达简单转换。两者的重点都是「每个元素都得到一个对应结果」。

4. 筛选与汇总

filter(function, iterable) 会保留函数返回真值的元素。传入的函数通常叫谓词(predicate),它只负责回答「这个元素是否符合条件」:

filter-basic.py
1
def is_adult(age):
2
return age >= 18
3
4
ages = [12, 18, 20, 15, 30]
5
adults = filter(is_adult, ages)
6
7
print(list(adults)) # [18, 20, 30]

和 map() 一样,filter() 返回的是惰性迭代器。条件简单时,也可以使用列表推导式:

filter-comprehension.py
1
ages = [12, 18, 20, 15, 30]
2
adults = [age for age in ages if age >= 18]
3
4
print(adults) # [18, 20, 30]

reduce() 用来把一组元素逐步合并成一个结果。它位于 functools 模块中,传入的函数每次接收「当前累计值」和「下一个元素」:

reduce-sum.py
1
from functools import reduce
2
3
def add(total, number):
4
return total + number
5
6
numbers = [1, 2, 3, 4]
7
total = reduce(add, numbers, 0)
8
9
print(total) # 10

上面的计算过程可以理解为 (((0 + 1) + 2) + 3) + 4。第三个参数 0 是初始累计值,它还能让空列表有明确的结果:

reduce-product.py
1
from functools import reduce
2
3
numbers = [2, 3, 4]
4
product = reduce(lambda total, number: total * number, numbers, 1)
5
6
print(product) # 24

reduce() 很灵活,但不一定是最易读的选择。求和优先使用 sum(),求最大值或最小值优先使用 max()、min();只有在确实需要按顺序累积自定义结果时,才使用 reduce()。

5. 排序

sorted(iterable, key=None, reverse=False) 会返回一个新的列表,不会修改原来的可遍历对象。key 接收一个函数,用来告诉 Python 比较每个元素的哪个值:

sorted-basic.py
1
scores = [80, 95, 68, 90]
2
3
print(sorted(scores)) # [68, 80, 90, 95]
4
print(sorted(scores, reverse=True)) # [95, 90, 80, 68]

如果元素是字典或对象,可以使用 key 提取排序依据:

sorted-key.py
1
students = [
2
{"name": "小明", "score": 88},
3
{"name": "小红", "score": 95},
4
{"name": "小刚", "score": 82},
5
]
6
7
ordered = sorted(students, key=lambda student: student["score"], reverse=True)
8
print(ordered)

sorted() 和列表的 sort() 不同:sorted() 返回新列表,可以处理任何可遍历对象;sort() 是列表的方法,会直接修改原列表,并返回 None:

sort-in-place.py
1
numbers = [3, 1, 2]
2
result = numbers.sort()
3
4
print(numbers) # [1, 2, 3]
5
print(result) # None

key 函数只负责为每个元素提供比较值,不需要自己实现排序算法。Python 的排序是稳定的:当两个元素的 key 相同时,它们会保留原来的相对顺序。

6. 组合

map()、filter() 和 sorted() 可以组合起来,把数据处理过程写成清晰的步骤。下面先筛选成年人,再按年龄从大到小排序:

pipeline.py
01
users = [
02
{"name": "小明", "age": 17},
03
{"name": "小红", "age": 23},
04
{"name": "小刚", "age": 20},
05
]
06
07
adults = filter(lambda user: user["age"] >= 18, users)
08
ordered = sorted(adults, key=lambda user: user["age"], reverse=True)
09
10
print(list(ordered))

当步骤较多时,可以先把每一步命名为普通函数,再传给高阶函数。命名函数更容易调试和复用:

named-pipeline.py
01
users = [
02
{"name": "小明", "age": 17},
03
{"name": "小红", "age": 23},
04
{"name": "小刚", "age": 20},
05
]
06
07
def is_adult(user):
08
return user["age"] >= 18
09
10
def age_key(user):
11
return user["age"]
12
13
adults = filter(is_adult, users)
14
ordered = sorted(adults, key=age_key, reverse=True)

lambda 适合很短的单表达式逻辑,例如 lambda user: user["age"]。如果逻辑需要分支、异常处理或多行说明,就应该写成普通函数。高阶函数的目标是把「处理流程」和「具体规则」分开,而不是为了少写几行代码而强行嵌套表达式。

在 FastAPI 和 LangChain 项目中,这种思想会出现在请求校验、消息转换、工具回调和链式处理里:框架负责调用流程,开发者把某个步骤的具体行为以函数形式传进去。

正在验证登录状态
请稍候,验证完成后将继续显示文章内容