Skip to content

17|匿名函数与高阶函数

有些函数逻辑只有一行,专门起一个函数名显得冗余。Python 提供 lambda 写匿名函数。另外,函数可以作为参数传给其他函数,也可以作为返回值——这类接收或返回函数的函数叫高阶函数。

一、lambda 表达式

python
# 普通函数
def square(x):
    return x * x

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

lambda 参数: 表达式——只能写一行表达式,不能包含语句(如赋值、循环)。

lambda 适合真正只有一行的简单逻辑。逻辑一复杂,还是写 def

python
# 不好的 lambda:可读性差
process = lambda x: x.strip().lower().replace(" ", "_")

# 好的 def:有名字,可以加文档
def normalize_name(name):
    return name.strip().lower().replace(" ", "_")

二、高阶函数

sorted() 的 key 参数

排序时按自定义规则比较:

python
names = ["Charlie", "Bob", "Alice"]

# 按长度排序
sorted(names, key=len)
# ['Bob', 'Alice', 'Charlie']

# 按小写排序(忽略大小写)
sorted(names, key=str.lower)
# ['Alice', 'Bob', 'Charlie']

key 接收一个函数,sorted() 用这个函数的返回值作为排序依据。

python
# 按年龄排序(字典列表)
users = [
    {"name": "Alice", "age": 25},
    {"name": "Bob", "age": 20},
    {"name": "Charlie", "age": 30},
]

sorted(users, key=lambda u: u["age"])
# [{'name': 'Bob', 'age': 20}, {'name': 'Alice', 'age': 25}, ...]

map()

对序列的每个元素应用函数:

python
numbers = [1, 2, 3, 4]
squares = map(lambda x: x * x, numbers)
list(squares)   # [1, 4, 9, 16]

map() 返回迭代器,需要 list() 转成列表才能看到全部内容。

filter()

保留满足条件的元素:

python
numbers = [1, 2, 3, 4, 5, 6]
evens = filter(lambda x: x % 2 == 0, numbers)
list(evens)   # [2, 4, 6]

map/filter vs 推导式

功能相同的情况下,推导式通常更推荐:

python
# map
squares = list(map(lambda x: x * x, numbers))

# 推导式(推荐)
squares = [x * x for x in numbers]

# filter
evens = list(filter(lambda x: x % 2 == 0, numbers))

# 推导式(推荐)
evens = [x for x in numbers if x % 2 == 0]

推导式可读性更好,性能通常也更好。map/filter 配合 lambda 的写法在函数式编程风格中出现,但在 Python 社区中不是首选。

三、函数作为返回值

python
def make_adder(n):
    """返回一个加 n 的函数。"""
    def adder(x):
        return x + n
    return adder

add_five = make_adder(5)
print(add_five(10))   # 15
print(add_five(3))    # 8

add_five 是一个函数,它"记住"了 n = 5。这是闭包的典型应用。

四、常用内置高阶函数

python
# all/any:判断序列是否全部/任意满足条件
all([True, True, False])   # False
any([False, True, False])  # True

all(n > 0 for n in [1, 2, 3])   # True
any(n > 10 for n in [1, 2, 3])  # False
python
# max/min 的 key 参数
words = ["apple", "pie", "strawberry"]
max(words, key=len)   # 'strawberry',最长的单词

记忆锚点lambda 只能写一行表达式,复杂逻辑用 defsorted()key 参数自定义排序规则;map/filter 功能与推导式相同,推导式更推荐;函数可以作为参数和返回值;all/any 配合生成器表达式判断条件。