查看全课大纲(第 30 / 51 节)
- 1.Python 是什么?为什么值得学?
- 2.如何为 Python 编程准备一个“全家桶”环境?
- 3.Python 有哪几种执行方法?
- 4.行与缩进到底有什么用?
- 5.注释有什么用,怎么写?
- 6.变量:如何给数据起个好名字?
- 7.运算符的优先级和常见坑点是什么?
- 8.Python 中,数字和布尔值究竟有哪几种?
- 9.输入函数 `input()` 和文件读取 `open()` 怎么用?
- 10.如何将程序的结果展示给用户或保存下来?
- 11.CSV 文件怎么读怎么写才方便?
- 12.列表是什么,如何创建和访问它?
- 13.列表的修改操作,有哪些方法?
- 14.列表切片为什么能取到部分元素?排序和查找又该怎么用?
- 15.判断语句:如何让程序根据条件做不同的事?
- 16.for 循环如何遍历序列中的元素?
- 17.while 循环什么时候才会停?
- 18.while 循环的结束条件,你写对了吗?
- 19.循环中途想提前结束,怎么办?
- 20.`break` 和 `continue` 到底有什么区别?
- 21.列表推导式如何让代码更简洁高效?
- 22.字符串怎么定义、拼接和操作?
- 23.元组:为什么定义单个元素时要加逗号?
- 24.集合(set)怎么用?如何快速去重和做集合运算?
- 25.字典是什么,为什么比列表更方便?
- 26.字典的增删改查与遍历,如何避免 KeyError?
- 27.函数里的变量,为什么有的能用有的不能用?
- 28.在函数内部修改全局变量,为什么有时不生效?
- 29.函数里能修改全局变量吗?返回值怎么用?
- 30.匿名函数:如何用 lambda 快速定义简单函数?
- 31.面向对象编程是什么,为什么需要它?
- 32.类中的方法和属性到底怎么定义和使用?
- 33.如何控制对对象内部属性和方法的访问?
- 34.异常发生时,程序会怎样继续执行?
- 35.如何组织代码:包和模块
- 36.`if __name__ == '__main__'` 到底有什么用?
- 37.如何用 IDE 的 Debug 功能排查程序错误?
- 38.Matplotlib 绘图的第一步该做什么?
- 39.Figure 是什么,如何设置图形尺寸?
- 40.如何自定义 Matplotlib 的坐标轴?
- 41.如何为图表添加图例,让不同曲线一目了然?
- 42.饼图怎么画才能直观展示数据占比?
- 43.如何用 Matplotlib 绘制散点图?
- 44.柱状图怎么画?
- 45.如何使用 Matplotlib 绘制等高线图?
- 46.如何在 Matplotlib 中绘制子图?
- 47.zip 函数如何把多个列表“打包”在一起?
- 48.如何给可迭代对象加上索引?
- 49.random 模块如何生成随机数?
- 50.math 模块怎么用?
- 51.Counter 如何快速统计元素出现次数?
匿名函数:如何用 lambda 快速定义简单函数?
约 8 分钟
小象实战讲义 · Python 编程从入门到实践
在上一节,我们学习了如何用 def 关键字定义有名字的函数。但有时,我们只需要一个简单的、只用一次的计算逻辑,为它单独命名和定义显得有些繁琐。这时,匿名函数(lambda 函数)就派上用场了。本节将学习 lambda 函数的定义、使用场景以及它与普通函数的区别。
💡 核心导读
- 是什么:匿名函数是用
lambda关键字定义的、没有名字的简单函数。 - 怎么用:语法为
lambda 参数列表: 表达式,表达式的结果会自动返回。 - 关键限制:匿名函数只能包含一个表达式,不能写复杂的语句块(如循环、多行逻辑)。
- 典型场景:作为参数传递给其他函数(如
sort()方法的key参数),实现简洁的回调逻辑。 - 与普通函数的关系:功能上可以相互替代,但匿名函数更简洁,适用于简单、一次性的操作。
匿名函数的基本语法
匿名函数使用 lambda 关键字定义,其基本结构如下:
lambda 参数1, 参数2, ... : 表达式lambda:定义匿名函数的关键字。参数列表:与普通函数类似,可以接收零个或多个参数,用逗号分隔。::冒号分隔参数列表和函数体。表达式:匿名函数的“函数体”。这个表达式会被计算,其结果自动作为函数的返回值。注意,这里不能使用return关键字,也不能编写多行代码或多个语句。
下面是一个最简单的例子,它定义了一个计算两数之和的匿名函数:
# 定义一个匿名函数,计算两个数的和,并将其赋值给变量 sum_func
sum_func = lambda x, y: x + y
# 通过变量名调用这个匿名函数
result = sum_func(10, 20)
print(result) # 输出:3030虽然我们将匿名函数赋值给了变量 sum_func,但函数本身仍然是“匿名”的。sum_func 只是一个指向这个匿名函数的变量,我们可以像调用普通函数一样使用它。
匿名函数的典型使用场景
匿名函数最常见的用途是作为参数传递给另一个函数,这使得代码非常紧凑。
作为自定义函数的参数
假设我们有一个函数 xy_comp,它接收两个数字和一个函数作为参数,并用传入的函数对这两个数字进行计算。
# 定义一个函数,它接收两个数字和一个函数参数
def xy_comp(x, y, func):
"""使用传入的函数 func 计算 x 和 y"""
return func(x, y)
# 场景1:传入一个计算加法的匿名函数
add_result = xy_comp(3, 5, lambda a, b: a + b)
print("3 + 5 = {}".format(add_result))
# 场景2:传入一个计算乘法的匿名函数
mul_result = xy_comp(3, 5, lambda a, b: a * b)
print("3 * 5 = {}".format(mul_result))3 + 5 = 8
3 * 5 = 15这里,我们分别传入了两个不同的匿名函数给 xy_comp,从而得到了加法和乘法的结果。如果不用匿名函数,我们需要先定义两个有名字的函数(如 def my_add(a, b): 和 def my_mul(a, b):),再传进去,代码会显得冗余。
作为内置函数的参数
Python 许多内置函数或方法支持接收函数作为参数,匿名函数在这里大放异彩。一个经典的例子是列表的 sort() 方法中的 key 参数。
假设我们有一个字典列表,需要根据字典中的某个值进行排序。
# 一个包含字典的列表
people = [
{"name": "张三", "age": 25},
{"name": "李四", "age": 30},
{"name": "王五", "age": 20}
]
# 使用 sort() 方法,根据 'age' 字段进行升序排序
# key 参数接收一个函数,这个函数会应用于列表的每一个元素,并以其返回值作为排序依据
people.sort(key=lambda person: person["age"])
print("按年龄升序排序:")
for p in people:
print(p)
print("\n" + "="*30 + "\n")
# 重新初始化列表,演示降序排序
people = [
{"name": "张三", "age": 25},
{"name": "李四", "age": 30},
{"name": "王五", "age": 20}
]
# 使用 reverse=True 实现降序
people.sort(key=lambda p: p["age"], reverse=True)
print("按年龄降序排序:")
for p in people:
print(p)按年龄升序排序:
{'name': '王五', 'age': 20}
{'name': '张三', 'age': 25}
{'name': '李四', 'age': 30}
==============================
按年龄降序排序:
{'name': '李四', 'age': 30}
{'name': '张三', 'age': 25}
{'name': '王五', 'age': 20}key=lambda p: p["age"] 这行代码非常清晰地表达了排序规则:“对于列表中的每个元素 p,取其 'age' 键对应的值来比较大小”。
匿名函数与普通函数的对比
匿名函数是普通函数的一种简洁写法,但并非全能替代。下表总结了它们的核心区别:
| 特性 | 匿名函数 (lambda) | 普通函数 (def) |
|---|---|---|
| 定义关键字 | lambda | def |
| 函数名 | 无(匿名) | 有 |
| 函数体 | 只能是单个表达式 | 可以是任意复杂的语句块 |
| 返回值 | 表达式结果自动返回 | 需要使用 return 语句显式返回 |
| 适用场景 | 简单的、一次性的逻辑,常作为参数传递 | 复杂的、需要复用的逻辑 |
| 可读性 | 简单时非常简洁,复杂时降低可读性 | 结构清晰,适合封装复杂逻辑 |
简单来说:如果你的函数逻辑简单到可以写成一个表达式,并且不需要在其他地方重复调用,那么使用 lambda 会让代码更简洁。否则,请使用 def 定义普通函数。
📝 动手练一练
改写练习:下面的普通函数功能是判断一个数字是否为偶数。请尝试将其改写为一个功能相同的匿名函数,并调用它检查数字 7 和 10。
def is_even(n): return n % 2 == 0
👉 点击查看参考答案
思路:匿名函数需要一个参数 n,表达式为 n % 2 == 0。我们可以将其赋值给一个变量,然后调用。
# 将匿名函数赋值给变量 check_even
check_even = lambda n: n % 2 == 0
# 调用测试
print("7 是偶数吗? {}".format(check_even(7)))
print("10 是偶数吗? {}".format(check_even(10)))7 是偶数吗? False
10 是偶数吗? True- 排序应用:有一个字符串列表
['apple', 'Banana', 'cherry', 'Date']。请使用列表的sort()方法和匿名函数,实现不区分大小写的字母顺序排序(即期望结果为['apple', 'Banana', 'cherry', 'Date']按a, b, c, d排序)。
👉 点击查看参考答案
思路:list.sort() 的 key 参数可以接收一个函数,对每个元素进行处理后再排序。要实现不区分大小写,可以将每个元素都转换为大写后再比较。
fruits = ['apple', 'Banana', 'cherry', 'Date']
# 使用匿名函数,将每个水果名转换为大写作为排序键
fruits.sort(key=lambda x: x.upper())
print(fruits)['apple', 'Banana', 'cherry', 'Date']常见错误
| 错误写法 | 现象或报错 | 原因 | 正确写法 |
|---|---|---|---|
lambda x, y: return x + y | SyntaxError: invalid syntax | 匿名函数体是表达式,其值自动返回,不能使用 return 语句。 | lambda x, y: x + y |
f = lambda x: x*2 后直接 print(f),期望打印结果 8 | 打印出的是函数对象,而不是计算结果 8 | f 是函数对象本身,打印它不会执行函数。需要调用函数才能得到结果。 | f = lambda x: x*2 后使用 print(f(4)) |
| 在复杂逻辑中坚持使用 lambda | 代码可读性急剧下降 | Lambda 适用于简单表达式。强行嵌套或编写复杂 lambda 会使代码难以理解和维护。此时应使用 def 定义普通函数。 | 使用 def 定义多行、有名字的函数。 |
小结
- 匿名函数使用
lambda关键字定义,格式为lambda 参数: 表达式。 - 表达式的结果会自动成为函数的返回值,无需
return。 - 匿名函数的核心优势是简洁,特别适合作为参数传递给其他函数(如
sort(key=...))。 - 匿名函数只能包含一个表达式,不能编写多行语句或复杂逻辑,这是它与普通函数 (
def) 的主要区别。 - 如果函数逻辑很简单且只用一次,用 lambda;如果需要复用或逻辑复杂,用
def。
📋 行动清单
- 尝试将本节
xy_comp函数的例子,改用def定义两个普通函数(add和mul)来实现,对比两种写法的代码长度和直观感受。 - 找一个你之前写的列表,尝试用
sort(key=lambda ...)的方式,根据元素的某个属性或计算后的值进行排序。 - 把示例中的
sum_func换成另一个变量名再调用一次,体会“匿名函数”只是没有名字,赋值后仍可通过变量调用。
—— 小象教研组
配套资料 · 直接下载
课件、代码、数据集等配套资料全部免费,点击即可直接下载,无需分享或解锁。
- 下载第3章代码包:函数(含1 个 Notebook)ZIP · 3KB