第38集:lambda表达式

学习目标

  • 理解lambda表达式的概念
  • 掌握lambda表达式的基本语法
  • 学会lambda表达式与普通函数的区别
  • 掌握lambda在常见场景中的应用
  • 理解lambda表达式的局限性

一、什么是lambda表达式?

lambda表达式是一种匿名函数,即没有名字的函数。

基本语法

lambda 参数: 表达式

与普通函数的对比

特性 普通函数 lambda表达式
定义方式 def关键字 lambda关键字
函数名 需要命名 无名(匿名)
函数体 多行代码 单行表达式
复杂度 可以很复杂 只能写简单表达式
可读性 较低

对比示例

# 普通函数
def add(a, b):
    return a + b

# lambda表达式
add_lambda = lambda a, b: a + b

# 使用方式相同
print(add(5, 3))         # 输出:8
print(add_lambda(5, 3))  # 输出:8

生活类比

  • 普通函数:一家正规餐厅,有招牌、菜单、服务员
  • lambda表达式:路边摊,没有招牌,直接买就走

二、lambda表达式基本语法

基本形式

# 无参数
lambda: 表达式

# 一个参数
lambda x: 表达式

# 多个参数
lambda x, y, z: 表达式

示例1:无参数的lambda

say_hello = lambda: "Hello, World!"
print(say_hello())  # 输出:Hello, World!

get_current_time = lambda: __import__('datetime').datetime.now()
print(get_current_time())  # 输出:当前时间

示例2:单个参数的lambda

# 平方
square = lambda x: x * x
print(square(5))  # 输出:25

# 判断偶数
is_even = lambda x: x % 2 == 0
print(is_even(4))  # 输出:True
print(is_even(5))  # 输出:False

# 字符串转大写
to_upper = lambda s: s.upper()
print(to_upper("hello"))  # 输出:HELLO

示例3:多个参数的lambda

# 加法
add = lambda a, b: a + b
print(add(5, 3))  # 输出:8

# 三数相加
add_three = lambda a, b, c: a + b + c
print(add_three(1, 2, 3))  # 输出:6

# 计算矩形面积
area = lambda width, height: width * height
print(area(5, 3))  # 输出:15

示例4:带条件表达式的lambda

# 绝对值
abs_value = lambda x: x if x >= 0 else -x
print(abs_value(5))   # 输出:5
print(abs_value(-5))  # 输出:5

# 成绩等级
grade = lambda score: "A" if score >= 90 else ("B" if score >= 80 else "C")
print(grade(95))  # 输出:A
print(grade(85))  # 输出:B
print(grade(75))  # 输出:C

三、lambda表达式与内置函数

与map函数结合

# 对列表中的每个元素求平方
numbers = [1, 2, 3, 4, 5]
squared = list(map(lambda x: x * x, numbers))
print(squared)  # 输出:[1, 4, 9, 16, 25]

# 将字符串列表转大写
words = ["hello", "world", "python"]
upper_words = list(map(lambda s: s.upper(), words))
print(upper_words)  # 输出:['HELLO', 'WORLD', 'PYTHON']

与filter函数结合

# 筛选偶数
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 = ["apple", "banana", "pear", "orange", "kiwi"]
long_words = list(filter(lambda s: len(s) > 5, words))
print(long_words)  # 输出:['banana', 'orange']

与reduce函数结合

from functools import reduce

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

# 字符串拼接
words = ["Hello", " ", "World", "!"]
sentence = reduce(lambda x, y: x + y, words)
print(sentence)  # 输出:Hello World!

与sorted函数结合

# 按字符串长度排序
words = ["apple", "banana", "pear", "orange", "kiwi"]
sorted_by_length = sorted(words, key=lambda s: len(s))
print(sorted_by_length)  # 输出:['pear', 'kiwi', 'apple', 'banana', 'orange']

# 按绝对值排序
numbers = [3, -5, 2, -8, 1, -4]
sorted_by_abs = sorted(numbers, key=lambda x: abs(x))
print(sorted_by_abs)  # 输出:[1, 2, 3, -4, -5, -8]

四、lambda表达式的应用场景

场景1:排序

# 按年龄排序
students = [
    {"name": "小明", "age": 18},
    {"name": "小红", "age": 20},
    {"name": "小华", "age": 17}
]

sorted_students = sorted(students, key=lambda x: x["age"])
print(sorted_students)
# 输出:[{'name': '小华', 'age': 17}, {'name': '小明', 'age': 18}, {'name': '小红', 'age': 20}]

场景2:数据处理

# 计算列表中所有正数的平方
numbers = [1, -2, 3, -4, 5, -6]
positive_squares = [lambda x: x * x for x in numbers if x > 0]  # 错误示例

# 正确方式:使用列表推导式
positive_squares = [x * x for x in numbers if x > 0]
print(positive_squares)  # 输出:[1, 9, 25]

# 使用lambda和map
positive_squares = list(map(lambda x: x * x, filter(lambda x: x > 0, numbers)))
print(positive_squares)  # 输出:[1, 9, 25]

场景3:回调函数

# 定义一个接受函数作为参数的函数
def process_numbers(numbers, func):
    """处理数字列表"""
    return [func(num) for num in numbers]

# 使用lambda作为回调
numbers = [1, 2, 3, 4, 5]

# 计算平方
squared = process_numbers(numbers, lambda x: x * x)
print(squared)  # 输出:[1, 4, 9, 16, 25]

# 计算立方
cubed = process_numbers(numbers, lambda x: x ** 3)
print(cubed)  # 输出:[1, 8, 27, 64, 125]

场景4:事件处理

# 模拟事件处理系统
class EventManager:
    def __init__(self):
        self.handlers = []
    
    def on_click(self, handler):
        """注册点击事件处理程序"""
        self.handlers.append(handler)
    
    def click(self):
        """触发点击事件"""
        for handler in self.handlers:
            handler()

# 创建事件管理器
manager = EventManager()

# 使用lambda注册事件处理
manager.on_click(lambda: print("按钮1被点击!"))
manager.on_click(lambda: print("按钮2被点击!"))
manager.on_click(lambda: print("按钮3被点击!"))

# 触发事件
manager.click()
# 输出:
# 按钮1被点击!
# 按钮2被点击!
# 按钮3被点击!

五、lambda表达式的局限性

限制1:只能包含一个表达式

# ❌ 错误:lambda不能包含多行语句
# bad_lambda = lambda x: 
#     if x > 0:
#         return x
#     else:
#         return -x

# ✅ 正确:使用条件表达式
good_lambda = lambda x: x if x > 0 else -x

限制2:不能包含赋值语句

# ❌ 错误:lambda不能包含赋值
# bad_lambda = lambda x: y = x + 1

# ✅ 正确:只返回表达式
good_lambda = lambda x: x + 1

限制3:不能包含print等语句

# ❌ 错误:print是语句,不是表达式
# bad_lambda = lambda x: print(x)

# ✅ 正确:如果需要print,用普通函数
def print_func(x):
    print(x)

限制4:可读性问题

# ❌ 复杂的lambda难以理解
complex_lambda = lambda x: (x * 2 + 1) if x > 0 else (abs(x) ** 2 - 1)

# ✅ 更好的方式:定义普通函数
def complex_func(x):
    if x > 0:
        return x * 2 + 1
    else:
        return abs(x) ** 2 - 1

六、实际应用案例

案例1:学生成绩处理

# 学生成绩列表
students = [
    {"name": "小明", "score": 85},
    {"name": "小红", "score": 92},
    {"name": "小华", "score": 78},
    {"name": "小李", "score": 88}
]

# 按成绩排序
sorted_students = sorted(students, key=lambda x: x["score"], reverse=True)
print("按成绩排序:")
for student in sorted_students:
    print(f"  {student['name']}: {student['score']}分")

# 筛选及格学生
passing_students = list(filter(lambda x: x["score"] >= 80, students))
print("\n及格学生:")
for student in passing_students:
    print(f"  {student['name']}: {student['score']}分")

案例2:商品价格计算

# 商品列表
products = [
    {"name": "手机", "price": 2999, "discount": 0.1},
    {"name": "电脑", "price": 5999, "discount": 0.15},
    {"name": "耳机", "price": 199, "discount": 0.05},
    {"name": "键盘", "price": 299, "discount": 0}
]

# 计算折后价格
calculate_price = lambda p: p["price"] * (1 - p["discount"])

for product in products:
    final_price = calculate_price(product)
    print(f"{product['name']}: 原价¥{product['price']}, 折后价¥{final_price:.2f}")

案例3:数据转换

# 温度转换
celsius_to_fahrenheit = lambda c: c * 9/5 + 32
fahrenheit_to_celsius = lambda f: (f - 32) * 5/9

print("温度转换:")
print(f"  25°C = {celsius_to_fahrenheit(25):.2f}°F")
print(f"  77°F = {fahrenheit_to_celsius(77):.2f}°C")

# 货币转换
usd_to_cny = lambda usd: usd * 7.2
cny_to_usd = lambda cny: cny / 7.2

print("\n货币转换:")
print(f"  $100 = ¥{usd_to_cny(100):.2f}")
print(f"  ¥720 = ${cny_to_usd(720):.2f}")

案例4:文本处理

# 文本处理函数
texts = [
    "  Hello World  ",
    "Python is AWESOME",
    "lambda expressions",
    "  PROGRAMMING  "
]

# 去除首尾空格并转小写
clean_text = lambda s: s.strip().lower()

cleaned_texts = list(map(clean_text, texts))
print("文本处理:")
for original, cleaned in zip(texts, cleaned_texts):
    print(f"  原文:'{original}' → 处理后:'{cleaned}'")

# 提取单词首字母
first_letter = lambda s: s[0] if s else ""
words = ["apple", "banana", "cherry"]
first_letters = list(map(first_letter, words))
print(f"\n首字母:{first_letters}")

七、lambda表达式的高级用法

用法1:立即执行

# 定义并立即执行lambda
result = (lambda x, y: x + y)(5, 3)
print(result)  # 输出:8

# 创建并使用lambda
square = (lambda x: x * x)
print(square(5))  # 输出:25

用法2:lambda返回函数

def make_multiplier(n):
    """创建乘法函数"""
    return lambda x: x * n

times2 = make_multiplier(2)
times3 = make_multiplier(3)
times10 = make_multiplier(10)

print(times2(5))   # 输出:10
print(times3(5))   # 输出:15
print(times10(5))  # 输出:50

用法3:lambda作为默认参数

def apply_operation(x, operation=lambda n: n * 2):
    """应用操作"""
    return operation(x)

print(apply_operation(5))                          # 输出:10
print(apply_operation(5, lambda n: n * 3))        # 输出:15
print(apply_operation(5, lambda n: n ** 2))       # 输出:25

用法4:嵌套lambda

# 嵌套lambda
nested = lambda x: (lambda y: x + y)

add_5 = nested(5)
print(add_5(3))  # 输出:8

add_10 = nested(10)
print(add_10(3))  # 输出:13

八、最佳实践

实践1:简单任务使用lambda

# ✅ 简单操作适合用lambda
numbers = [1, 2, 3, 4, 5]
squared = list(map(lambda x: x * x, numbers))

实践2:复杂逻辑使用普通函数

# ✅ 复杂逻辑用普通函数
def complex_operation(x):
    """复杂操作"""
    result = x
    for i in range(2, x):
        result += x % i
    return result

# 简单操作用lambda
numbers = [5, 10, 15]
results = list(map(complex_operation, numbers))

实践3:考虑可读性

# ❌ 过于复杂的lambda
bad = lambda x: x ** 2 if x % 2 == 0 else x ** 3 if x > 0 else abs(x)

# ✅ 使用普通函数提高可读性
def transform(x):
    if x % 2 == 0:
        return x ** 2
    elif x > 0:
        return x ** 3
    else:
        return abs(x)

实践4:为lambda赋值有意义的名字

# ✅ 有意义的变量名
is_positive = lambda x: x > 0
to_uppercase = lambda s: s.upper()
calculate_area = lambda w, h: w * h

# 使用
print(is_positive(5))         # 输出:True
print(to_uppercase("hello"))  # 输出:HELLO
print(calculate_area(5, 3))   # 输出:15

九、常见错误与调试

错误1:lambda包含多个表达式

# ❌ 错误
# bad = lambda x: y = x + 1; y * 2

# ✅ 正确:只使用一个表达式
good = lambda x: (x + 1) * 2

错误2:lambda中缺少冒号

# ❌ 错误
# bad = lambda x x * 2

# ✅ 正确
good = lambda x: x * 2

错误3:lambda中缺少return

# ❌ 错误:不需要return
# bad = lambda x: return x * 2

# ✅ 正确:lambda自动返回表达式结果
good = lambda x: x * 2

调试技巧:打印lambda信息

# 查看lambda的类型
add = lambda x, y: x + y
print(type(add))  # 输出:<class 'function'>

# 查看__name__属性
print(add.__name__)  # 输出:<lambda>

十、小结

知识点 说明
lambda语法 lambda 参数: 表达式
匿名性 没有函数名
单行 只能包含一个表达式
应用场景 map、filter、sorted等
局限性 不能包含语句、赋值等
建议 简单任务用lambda,复杂任务用函数

十一、课后练习

练习1

使用lambda表达式定义一个计算立方的函数。

练习2

使用lambda和filter筛选出列表中的奇数。

练习3

使用lambda和sorted按字符串长度排序。

练习4

定义一个接受lambda作为参数的函数,实现对列表的处理。

练习5

使用lambda表达式创建一个函数生成器(返回函数的函数)。

« 上一篇 变量作用域 下一篇 » 递归函数基础