Skip to content

Lambda 函数与函数式编程

简洁的匿名函数 —— 一行代码解决问题


什么是 Lambda 函数?

Lambda 函数是匿名函数(没有名字的函数),用于简单的一次性操作。

语法

python
lambda 参数: 表达式

对比

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

# Lambda 函数(等价)
square = lambda x: x ** 2

print(square(5))  # 25

基本用法

示例 1:简单运算

python
# 加法
add = lambda x, y: x + y
print(add(3, 5))  # 8

# BMI 计算
bmi = lambda weight, height: weight / (height ** 2)
print(bmi(70, 1.75))  # 22.86

# 判断成年
is_adult = lambda age: age >= 18
print(is_adult(25))  # True

示例 2:与内置函数配合

python
# sorted() + lambda
students = [
    {'name': 'Alice', 'age': 25, 'gpa': 3.8},
    {'name': 'Bob', 'age': 22, 'gpa': 3.5},
    {'name': 'Carol', 'age': 24, 'gpa': 3.9}
]

# 按 GPA 排序
sorted_by_gpa = sorted(students, key=lambda s: s['gpa'], reverse=True)
for s in sorted_by_gpa:
    print(f"{s['name']}: {s['gpa']}")

# 按年龄排序
sorted_by_age = sorted(students, key=lambda s: s['age'])

map()、filter()、reduce()

1. map():对每个元素应用函数

python
# 普通方式
incomes = [50000, 60000, 75000, 80000]
incomes_after_tax = []
for income in incomes:
    incomes_after_tax.append(income * 0.75)

# 使用 map + lambda
incomes_after_tax = list(map(lambda x: x * 0.75, incomes))
print(incomes_after_tax)  # [37500, 45000, 56250, 60000]

# 列表推导式(更 Pythonic)
incomes_after_tax = [x * 0.75 for x in incomes]

社科应用

python
# 收入对数转换
import math
incomes = [45000, 60000, 75000, 90000]
log_incomes = list(map(lambda x: math.log(x), incomes))

# 标准化分数
scores = [85, 92, 78, 88]
mean = sum(scores) / len(scores)
std_scores = list(map(lambda x: (x - mean) / 10, scores))

2. filter():筛选元素

python
ages = [18, 25, 16, 30, 15, 40, 12, 35]

# 筛选成年人
adults = list(filter(lambda age: age >= 18, ages))
print(adults)  # [18, 25, 30, 40, 35]

# 筛选高收入者
incomes = [45000, 75000, 120000, 55000, 95000]
high_earners = list(filter(lambda x: x > 70000, incomes))
print(high_earners)  # [75000, 120000, 95000]

# 列表推导式(更推荐)
adults = [age for age in ages if age >= 18]

3. reduce():累积计算

python
from functools import reduce

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

# 找最大值
scores = [85, 92, 78, 95, 88]
max_score = reduce(lambda a, b: a if a > b else b, scores)
print(max_score)  # 95

# 但更好的方式是用内置函数
max_score = max(scores)

实战案例

案例 1:数据清洗流水线

python
# 原始数据
raw_incomes = [50000, -1000, 75000, 0, 120000, 9999999, 60000]

# 清洗流水线
clean_incomes = list(
    filter(lambda x: 0 < x < 1000000,  # 筛选有效值
           map(lambda x: round(x, -3),  # 四舍五入到千位
               raw_incomes))
)
print(clean_incomes)  # [50000, 75000, 120000, 60000]

案例 2:按多个条件排序

python
respondents = [
    {'id': 1, 'age': 30, 'income': 75000},
    {'id': 2, 'age': 25, 'income': 85000},
    {'id': 3, 'age': 25, 'income': 70000},
    {'id': 4, 'age': 30, 'income': 90000}
]

# 先按年龄,再按收入排序
sorted_data = sorted(respondents, key=lambda r: (r['age'], r['income']))

for r in sorted_data:
    print(f"ID{r['id']}: {r['age']}岁, ${r['income']:,}")

案例 3:动态生成函数

python
def make_multiplier(n):
    """返回一个乘以 n 的函数"""
    return lambda x: x * n

# 创建不同的倍数函数
double = make_multiplier(2)
triple = make_multiplier(3)
multiply_by_10 = make_multiplier(10)

print(double(5))           # 10
print(triple(5))           # 15
print(multiply_by_10(5))   # 50

# 应用:不同的税率计算器
def make_tax_calculator(rate):
    return lambda income: income * rate

tax_low = make_tax_calculator(0.10)
tax_mid = make_tax_calculator(0.20)
tax_high = make_tax_calculator(0.30)

income = 100000
print(f"低税率: ${tax_low(income):,.0f}")
print(f"中税率: ${tax_mid(income):,.0f}")
print(f"高税率: ${tax_high(income):,.0f}")

Lambda vs 普通函数

特性Lambda普通函数
语法lambda x: x**2def f(x): return x**2
名称匿名有名称
复杂度单行表达式可多行
文档无法添加可添加文档字符串
适用场景简单、一次性复杂、可复用

何时用 Lambda?

  • 简单的一次性操作
  • 作为参数传递(sorted(key=...)
  • map/filter 中的简单逻辑

何时用普通函数?

  • 逻辑复杂(多行代码)
  • 需要文档说明
  • 需要复用

列表推导式 vs Lambda

对于大多数情况,列表推导式比 lambda 更 Pythonic:

python
numbers = [1, 2, 3, 4, 5]

# 使用 map + lambda
squares = list(map(lambda x: x**2, numbers))

# 使用列表推导式(更好)
squares = [x**2 for x in numbers]

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

# 使用列表推导式(更好)
evens = [x for x in numbers if x % 2 == 0]

常见陷阱

陷阱 1:闭包中的变量绑定

python
#  错误示例
functions = []
for i in range(3):
    functions.append(lambda x: x + i)

print(functions[0](10))  # 期望12,实际12
print(functions[1](10))  # 期望11,实际12
print(functions[2](10))  # 期望12,实际12
# 所有函数都使用最后的 i 值(2)

#  正确做法:使用默认参数
functions = []
for i in range(3):
    functions.append(lambda x, i=i: x + i)

print(functions[0](10))  # 10
print(functions[1](10))  # 11
print(functions[2](10))  # 12

陷阱 2:过度使用导致代码难读

python
#  难以理解
result = list(filter(lambda x: x[1] > 50000 and x[2] < 40,
                     map(lambda p: (p['name'], p['income'], p['age']),
                         [r for r in data if r['gender'] == 'M'])))

#  清晰的方式
male_respondents = [r for r in data if r['gender'] == 'M']
high_income_young = [
    (r['name'], r['income'], r['age'])
    for r in male_respondents
    if r['income'] > 50000 and r['age'] < 40
]

练习题

练习 1:使用 Lambda 排序

python
students = [
    ('Alice', 25, 3.8),
    ('Bob', 22, 3.5),
    ('Carol', 24, 3.9),
    ('David', 23, 3.6)
]

# 任务:按以下方式排序
# 1. 按 GPA 从高到低
# 2. 按年龄从小到大
# 3. 按名字字母顺序

练习 2:数据转换

python
incomes = [45000, 60000, 75000, 90000, 120000]

# 使用 map + lambda:
# 1. 计算税后收入(税率25%)
# 2. 转换为万元(除以10000)
# 3. 保留1位小数

练习 3:综合应用

python
data = [
    {'name': 'Alice', 'age': 25, 'score': 85},
    {'name': 'Bob', 'age': 30, 'score': 55},
    {'name': 'Carol', 'age': 28, 'score': 92},
    {'name': 'David', 'age': 22, 'score': 78}
]

# 任务:
# 1. 筛选出及格的学生(score >= 60)
# 2. 按分数从高到低排序
# 3. 只保留姓名和分数

下一步

在下一节中,我们将学习 模块与包管理,了解如何组织和导入代码。

继续!

基于 MIT 许可证发布。内容版权归作者所有。