Python: 高阶函数与Lambda

Python 中函数也是一种"值",可以像数字、字符串一样赋值给变量、传给其他函数。利用这个特性,我们可以写出非常简洁、优雅的代码。高阶函数就是接收函数作为参数或返回函数的函数。这一课会让你打开新世界的大门。


1. 函数是一等公民

在 Python 中,函数可以像普通值一样操作:

▶ 示例:函数作为值传递

PYTHON
def say_hello(name):
    return f"你好,{name}"

# 把函数赋值给变量
my_func = say_hello
print(my_func("Alice"))      # 你好,Alice

# 函数可以作为参数传递
def greet_with(func, name):
    return func(name)

print(greet_with(say_hello, "Bob"))   # 你好,Bob

# 函数可以作为返回值
def create_greeter(greeting):
    def greeter(name):
        return f"{greeting},{name}!"
    return greeter

say_hi = create_greeter("嗨")
say_hello = create_greeter("你好")

print(say_hi("Alice"))       # 嗨,Alice!
print(say_hello("Bob"))    # 你好,Bob!
▶ 试一试

输出:

TEXT 📖 仅展示
# 函数定义成功
💡 "函数是一等公民"是什么意思? 就是说函数和整数、字符串、列表是同一等级的,可以做一样的事:赋值给变量、放进列表、作为参数传递、作为返回值。这种编程范式叫"函数式编程"。



2. map():批量转换

map() 对序列中的每个元素执行同一个函数,返回一个新迭代器:

▶ 示例:map 批量转换

PYTHON
# 把列表中的每个数字平方
numbers = [1, 2, 3, 4, 5]
squared = list(map(lambda x: x ** 2, numbers))
print(squared)              # [1, 4, 9, 16, 25]

# 字符串列表转大写
fruits = ["apple", "banana", "cherry"]
upper_fruits = list(map(str.upper, fruits))
print(upper_fruits)         # ['APPLE', 'BANANA', 'CHERRY']

# 摄氏转华氏
temps_c = [0, 10, 20, 30, 40]
temps_f = list(map(lambda c: c * 9 / 5 + 32, temps_c))
print(temps_f)              # [32.0, 50.0, 68.0, 86.0, 104.0]
▶ 试一试

输出:

TEXT 📖 仅展示
# 执行成功

map() 等价于列表推导式: map(f, seq)[f(x) for x in seq]。选哪个主要看个人偏好——推导式更"Python 风格"。



3. filter():批量筛选

filter() 筛选出使函数返回 True 的元素:

▶ 示例:filter 筛选数据

PYTHON
# 筛选出偶数
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
evens = list(filter(lambda x: x % 2 == 0, numbers))
print(evens)                # [2, 4, 6, 8, 10]

# 筛选出长度 >= 5 的单词
words = ["cat", "elephant", "dog", "giraffe", "ant"]
long_words = list(filter(lambda w: len(w) >= 5, words))
print(long_words)           # ['elephant', 'giraffe']

# 筛选出非空字符串
data = ["hello", "", "world", "", "python"]
non_empty = list(filter(None, data))   # None 表示"去掉假值"
print(non_empty)            # ['hello', 'world', 'python']
▶ 试一试

输出:

TEXT 📖 仅展示
# 执行成功

filter() 也等价于推导式: filter(f, seq)[x for x in seq if f(x)]。用 None 作为函数时,等价于去掉所有假值(""0NoneFalse 等)。



4. sorted() 高阶用法

第 11 课学了 sorted()key 参数,这里更深入地看看:

▶ 示例:sorted 自定义排序

PYTHON
# 按对象的某个属性排序
students = [
    {"name": "Alice", "score": 85},
    {"name": "Bob", "score": 92},
    {"name": "Charlie", "score": 78},
]

# 按分数降序
ranked = sorted(students, key=lambda s: s["score"], reverse=True)
for s in ranked:
    print(f"{s['name']}: {s['score']}")

# 按名字长度排序
sorted_by_name = sorted(students, key=lambda s: len(s["name"]))
print([s["name"] for s in sorted_by_name])   # ['Alice', 'Charlie', 'Bob']
▶ 试一试

输出:

TEXT 📖 仅展示
# 执行成功

▶ 示例:多级排序(难度⭐⭐)

PYTHON
# 先按分数降序,分数相同按名字字母顺序
data = [
    ("Alice", 85),
    ("Bob", 92),
    ("Charlie", 85),
    ("赵六", 92),
]

def sort_key(item):
    # 返回元组:先按分数降序(负数 = 反序),再按名字
    return (-item[1], item[0])

sorted_data = sorted(data, key=sort_key)
for name, score in sorted_data:
    print(f"{name}: {score}")
▶ 试一试

运行结果:

TEXT 📖 仅展示
Bob: 92
赵六: 92
Charlie: 85
Alice: 85


5. reduce():累积计算

reduce() 把序列中的元素累积起来,每次用函数处理两个元素。它不在内置函数中,需要从 functools 导入:

▶ 示例:reduce 累积计算

PYTHON
from functools import reduce

# 计算所有数字的乘积
numbers = [1, 2, 3, 4, 5]
product = reduce(lambda x, y: x * y, numbers)
print(product)              # 120(1×2×3×4×5)

# 找最大值
max_val = reduce(lambda a, b: a if a > b else b, [3, 1, 4, 1, 5])
print(max_val)              # 5

# 拼接字符串
words = ["Hello", " ", "World", " ", "Python"]
sentence = reduce(lambda a, b: a + b, words)
print(sentence)             # Hello World Python
▶ 试一试

输出:

TEXT 📖 仅展示
# 执行成功

(1) reduce() 的执行过程

PYTHON
# reduce(lambda x, y: x + y, [1, 2, 3, 4])
# 第1步:x=1, y=2 → 3
# 第2步:x=3, y=3 → 6
# 第3步:x=6, y=4 → 10
# 结果:10
💡 reduce() vs 循环: 任何 reduce() 能做的事,for 循环也能做。reduce() 的优点是代码更简洁、更"声明式"——你在说"我要做什么"而不是"我要怎么做"。缺点是初次接触的人可能看不懂。



6. Lambda 表达式深入

Lambda 的名字来自 λ(希腊字母),本质就是匿名函数——没有名字、用完就扔的小函数。

(1) Lambda vs 普通函数

▶ 示例:Lambda 对比普通函数

PYTHON
# 普通函数
def double(x):
    return x * 2

# Lambda 表达式
double = lambda x: x * 2

print(double(5))            # 10
▶ 试一试

输出:

TEXT 📖 仅展示
# 函数定义成功

(2) Lambda 的完整语法

PYTHON
lambda 参数: 表达式
# ↑ 等价于
def 匿名函数(参数):
    return 表达式

(3) 多个参数

▶ 示例:Lambda 多个参数

PYTHON
add = lambda a, b: a + b
print(add(3, 5))            # 8

# 三元表达式在 lambda 中
max_val = lambda a, b: a if a > b else b
print(max_val(10, 20))      # 20
▶ 试一试

输出:

TEXT 📖 仅展示
# 执行成功

(4) 什么时候用 Lambda

▶ 示例:Lambda 适用场景

PYTHON
# ✅ 适合:简单的一行变换,作为高阶函数的参数
numbers = [1, 2, 3, 4]
result = list(map(lambda x: x ** 2, numbers))

# ❌ 不适合:逻辑复杂,需要多行
# 这种应该写成普通 def 函数
▶ 试一试

输出:

TEXT 📖 仅展示
# 函数定义成功
💡 Lambda 的适用原则: 如果逻辑需要写超过一行表达式,或者需要 if-elif 多分支,就别用 lambda 了——写普通函数更清晰。Lambda 的优雅在于"极简"。



7. 常见应用场景


❓ 常见问题

Q map() 和列表推导式哪个更好?
A Python 社区更偏好列表推导式——更直观、更 Pythonic。map() 的优势是:① 当你有现成的函数名时更短(map(str.upper, seq) vs [s.upper() for s in seq]);② 返回的是惰性迭代器,大数据量时省内存。多数场景下,列表推导式是更好的选择。
Q Lambda 能不能写多行?
A 不能。Lambda 的语法限制它只能写单行表达式。需要多行逻辑时,定义普通函数。Python 的 lambda 比其他语言(如 JavaScript)的功能弱很多——这是故意的,因为 Guido(Python 之父)认为"显式优于隐式"。
Q reduce() 在现代 Python 中还用吗?
A 用得不多。Guido 本人不太喜欢 reduce(),认为它太难理解。大多数 reduce() 的场景可以用循环替代,或者有更直接的函数(如 sum()max())。不过在函数式编程中,reduce() 仍然是一个重要的概念。

📖 小节


📝 作业

  1. 基础题(难度⭐):给定列表 nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],用 map()filter() 分别实现:筛选出奇数并计算它们的平方。提示:先用 filter 筛奇数,再用 map 平方。

  2. 进阶题(难度⭐⭐):给定字典列表 products = [{"name": "A", "price": 100}, {"name": "B", "price": 80}, {"name": "C", "price": 120}],用 sorted() 按价格降序排序,并输出名称和价格。

  3. 挑战题(难度⭐⭐⭐):用 reduce() 实现 flatten(nested_list) 函数,把嵌套列表"展平"一层。例如 flatten([[1, 2], [3, 4], [5]]) 返回 [1, 2, 3, 4, 5]提示reduce 中每次用 + 合并两个列表。完成后用列表推导式实现同样的功能,比较两种写法的差异。

Web-Tutorial.com

Web-Tutorial 技术团队

由多位开发者共同维护的编程教程平台。每篇教程由对应领域的开发者编写和审核,确保内容准确可靠。如发现任何问题,欢迎向我们反馈。

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏