目录
一、匿名函数
1、匿名函数 vs 普通函数
2、lambda 是匿名函数的实现方式
3、lambda 的常见用途(匿名函数的典型使用)
4、匿名函数的特点与局限总结
二、高阶函数
1. 什么是高阶函数
2. Python 内置的常见高阶函数
2.1 map(func, iterable)
2.2 filter(func, iterable)
2.3 reduce(func, iterable[, initializer])
2.4 sorted(iterable, key=None, reverse=False)
2.5 any(iterable) 和 all(iterable)
2.6. max(iterable, key=func) 和 min(iterable, key=func)
3. 自定义高阶函数的典型场景
3.1 函数作为参数传入
3.2 函数作为返回值返回
4. 总结:高阶函数的优点
5. 常用高阶函数功能速查表
三、匿名函数lambda与高阶函数的混合使用
1. map() + lambda
2. filter() + lambda
3. sorted() + lambda
4. reduce() + lambda (需导入)
5. lambda + 自定义高阶函数
四、变量作用域
1. 什么是变量作用域?
2.LEGB 查找顺序(变量解析规则)
3. 内置作用域示例(Built-in)
4.global 和 nonlocal 关键词的作用
4.1 global: 修改全局变量
4.2 nonlocal: 修改外层非全局变量(通常用于闭包)
5. 变量作用域表格
五、递归函数
1.概念
1.1 函数结构
1.2 基本步骤
1.3 递归示例
1.3.1 阶乘定义
1.3.2 斐波那契数列
2.怎么找 "边界墙" ?
2.1 什么是“边界墙”?
2.2 找边界墙的两个关键思维
lambda 是实现匿名函数的语法,匿名函数是 lambda 的核心用途。
匿名函数(Anonymous Function)是指没有名字的函数,它们的设计初衷是为了在需要临时函数对象的场合使用。Python 中通过 lambda
表达式来定义匿名函数,因此:
lambda 表达式就是 Python 中创建匿名函数的唯一方式。
特性 | 普通函数(def) | 匿名函数(lambda) |
---|---|---|
是否有函数名 | 有(例如:def foo(): ) |
没有,用变量绑定或直接使用 |
写法复杂度 | 可以写多行语句 | 只能写一行表达式 |
功能复杂度 | 可包含任意逻辑、条件、循环等 | 仅限简单表达式 |
是否推荐长期使用 | 是,用于复用和清晰代码结构 | 否,适用于临时使用场景 |
语法回顾:
lambda 参数1, 参数2, ... : 表达式
这个表达式的值就是函数的返回值。
举例:
# 普通函数定义
def multiply(x, y):
return x * y
# 匿名函数定义(lambda)
multiply_lambda = lambda x, y: x * y
# 调用比较
print(multiply(3, 4)) # 输出: 12
print(multiply_lambda(3, 4)) # 输出: 12
注意:lambda 定义的是匿名函数本体,而不是执行调用。 你可以把这个函数赋值给一个变量,也可以直接作为参数传入函数(更常见)。
匿名函数适用于那些你不想给函数起名,且只使用一次的场景,例如:
排序:
data = [(1, 2), (3, 1), (5, 0)]
sorted_data = sorted(data, key=lambda x: x[1])
# 按照第二个元素排序
map()
:对序列进行转换
nums = [1, 2, 3]
squares = list(map(lambda x: x**2, nums))
filter()
:条件筛选
nums = [1, 2, 3, 4]
even = list(filter(lambda x: x % 2 == 0, nums))
reduce()
:累积操作(需导入)
from functools import reduce
result = reduce(lambda x, y: x + y, [1, 2, 3, 4])
✅ 优点:
简洁、写法短;
避免定义额外函数名;
用于函数式编程、事件处理、回调、临时操作等场景很方便。
❌ 局限:
只能写单个表达式,不能写多行语句;
不支持复杂的控制结构(如
if
-else
多分支、for
循环);调试困难,不利于代码复用和维护;
无法使用注释、函数文档(docstring)等功能。
在 Python 中,函数是一等对象,可以像变量一样传递、赋值、作为返回值。
因此,高阶函数是指满足以下任意一个条件的函数:
将函数作为参数传入
返回一个函数
示例:
def apply(func, x):
return func(x)
def square(n):
return n * n
print(apply(square, 5)) # 输出 25
上述 apply
就是一个高阶函数,它接受另一个函数 func
作为参数。
以下为 Python 中最常用的高阶函数及其使用方式:
map(func, iterable)
对可迭代对象的每个元素应用函数,并返回一个新的迭代器。
nums = [1, 2, 3, 4]
squares = list(map(lambda x: x ** 2, nums))
# 输出: [1, 4, 9, 16]
filter(func, iterable)
筛选可迭代对象中使 func(x)
返回 True 的元素。
nums = [1, 2, 3, 4, 5]
evens = list(filter(lambda x: x % 2 == 0, nums))
# 输出: [2, 4]
reduce(func, iterable[, initializer])
需要引入 functools
模块,用于连续将 func
应用于序列(从左至右),把结果累积起来。
from functools import reduce
nums = [1, 2, 3, 4]
product = reduce(lambda x, y: x * y, nums)
# 输出: 24
sorted(iterable, key=None, reverse=False)
带 key
参数的排序函数,key
接收一个函数用于提取排序依据。
words = ["banana", "apple", "pear"]
sorted_words = sorted(words, key=lambda x: len(x))
# 输出: ['pear', 'apple', 'banana']
any(iterable)
和 all(iterable)
虽然不是典型的接受函数参数,但常配合生成器表达式一起用,逻辑上仍具有高阶特性。
nums = [0, 1, 2]
print(any(x > 1 for x in nums)) # True
print(all(x >= 0 for x in nums)) # True
max(iterable, key=func)
和 min(iterable, key=func)
也可接收函数作为 key
参数,用于提取比较依据。
students = [{"name": "Alice", "score": 88}, {"name": "Bob", "score": 95}]
best = max(students, key=lambda s: s["score"])
# 输出: {'name': 'Bob', 'score': 95}
大家可以查看python官方文档查看更多的函数使用方法:
Python 解释器内置了很多函数和类型,任何时候都能使用。
def operate(x, y, func):
return func(x, y)
result = operate(3, 5, lambda a, b: a + b)
# 输出: 8
这就是闭包(closure)的一种表现形式。
def make_multiplier(n):
def multiplier(x):
return x * n
return multiplier
times3 = make_multiplier(3)
print(times3(4)) # 输出: 12
我们在下一篇文章会详细介绍闭包的相关知识。
增强代码的通用性和抽象能力
配合 lambda 表达式、推导式使代码更简洁
适合用于数据处理、管道处理、函数组合等场景
是理解装饰器、闭包、函数式编程的基础
函数名 | 功能描述 | 是否返回迭代器 |
---|---|---|
map |
对每个元素应用函数 | 是 |
filter |
保留使函数返回 True 的元素 | 是 |
reduce |
将函数连续应用于序列 | 否 |
sorted |
可基于函数排序 | 否 |
max/min |
使用函数提取比较依据 | 否 |
any/all |
结合生成器表达式检查逻辑 | 否 |
map()
+ lambda对序列中每个元素执行某种转换
nums = [1, 2, 3]
doubled = list(map(lambda x: x * 2, nums))
print(doubled) # [2, 4, 6]
filter()
+ lambda筛选符合条件的元素
nums = [1, 2, 3, 4, 5]
even = list(filter(lambda x: x % 2 == 0, nums))
print(even) # [2, 4]
sorted()
+ lambda根据某个规则排序
students = [('Tom', 88), ('Jerry', 95), ('Anna', 72)]
# 按成绩排序
sorted_students = sorted(students, key=lambda x: x[1])
print(sorted_students)
reduce()
+ lambda (需导入)from functools import reduce
nums = [1, 2, 3, 4]
product = reduce(lambda x, y: x * y, nums)
print(product) # 24
你也可以自己写高阶函数,然后把 lambda 传进去:
def apply_twice(func, value):
return func(func(value))
result = apply_twice(lambda x: x + 3, 4)
print(result) # ((4 + 3) + 3) = 10
综合案例:学生成绩处理
import random
students = ['Alice', 'Bob', 'Charlie']
scores = [{'name': s, 'score': random.randint(50, 100)} for s in students]
# 过滤出成绩大于 60 的
passed = list(filter(lambda x: x['score'] >= 60, scores))
# 按成绩排序
sorted_passed = sorted(passed, key=lambda x: x['score'], reverse=True)
# 取出名字列表
names = list(map(lambda x: x['name'], sorted_passed))
print("及格学生:", names)
变量作用域:变量在程序中可见和可用的范围。
Python 中有 4 种作用域(记作 LEGB):
缩写 | 名称 | 说明 |
---|---|---|
L | Local | 函数内部定义的局部变量 |
E | Enclosing | 嵌套函数的外部函数中的变量(闭包相关) |
G | Global | 模块级别定义的变量(全局变量) |
B | Built-in | Python 解释器预定义的内置变量(如 len ) |
当你在函数中访问一个变量时,Python 会按照 LEGB 的顺序查找:
Local -> Enclosing -> Global -> Built-in
一旦在某一层找到了这个变量,就不再继续向外查找。
示例讲解:LEGB 顺序
x = "global" # Global
def outer():
x = "enclosing" # Enclosing
def inner():
x = "local" # Local
print(x)
inner()
outer()
# 输出:local
如果我们注释掉
x = "local"
,它就会打印enclosing
,依此类推。
print(len("hello")) # len 是内置函数
如果你不小心写了:
len = 10
print(len("abc")) # ❌ 会报错,因为 len 被你覆盖成了变量!
所以不要随意覆盖内置变量名!
global
和 nonlocal
关键词的作用4.1 global
: 修改全局变量x = 5
def change_global():
global x
x = 10
change_global()
print(x) # 输出 10
4.2 nonlocal
: 修改外层非全局变量(通常用于闭包)def outer():
x = 5
def inner():
nonlocal x
x = 10
inner()
print(x)
outer() # 输出 10
类型 | 定义在哪 | 是否能在函数中访问 | 是否能修改(默认) |
---|---|---|---|
Local | 函数内部 | ✅ | ✅ |
Enclosing | 外层嵌套函数 | ✅(闭包) | nonlocal 才能修改 |
Global | 模块最外层 | ✅ | global 才能修改 |
Built-in | Python 自带 | ✅ | ❌(不可改) |
递归是指函数直接或间接调用自身的过程。递归通常用于解决分解成相似子问题的复杂问题。
递归函数通常由两个部分组成:
终止条件:用于确保递归能够停止,避免无限递归。
递归调用:函数在其内部调用自身,传递简化或减少的参数,以解决更小的子问题。
定义递归函数:在函数体内调用函数自身。
设定终止条件:确保递归能终止。
逐步简化问题:通过传递较小的参数递归求解,直至终止条件满足。
递归:先递进,再回归。
n! = n * (n-1) * (n-2) * ... * 1
递归公式:n! = n * (n-1)!
,终止条件:0! = 1
示例代码:
def factorial(n):
# 终止条件:n为0或1时,返回1
if n == 0 or n == 1:
return 1
# 递归调用:n * (n-1)!
return n * factorial(n - 1)
# 测试
print(factorial(6)) # 输出 720
斐波那契数列(Fibonacci sequence)是一种经典的数列,它的特点是从第 3 项开始,每一项都等于前两项之和。前两项通常定义为:
F(0) = 0
F(1) = 1
从 F(2) 开始:
F(2) = F(1) + F(0) = 1 + 0 = 1
F(3) = F(2) + F(1) = 1 + 1 = 2
使用递归的思想实现斐波那契数列
参考代码:
def fb(n):
if n == 0 or n == 1:
return n
return fb(n - 1) + fb(n - 2)
递归数列的关键是找到边界墙!
“边界墙”就是:
不再继续递归的条件
让递归有机会返回、不陷入无限调用
你可以把递归想成一口井,你不断往下跳(每次递归),但你得知道什么时候到底了(边界墙),不然你永远掉下去。
一句话:边界墙就是终止条件;
作用是避免无限递归,保证能返回结果;
通常写在递归函数的最前面。
找最简单、最小的情况 通常是:n=0
或 n=1
,这时候你不需要再递归,可以直接返回结果。
问自己:什么时候我可以不再递归?
例子1:阶乘(n!)
def factorial(n):
if n == 1: # ⬅️ 这是边界墙
return 1
return n * factorial(n - 1)
递归思路:n! = n * (n-1)!
边界墙是 n == 1
,不能一直减,否则无限递归。
例子2:斐波那契数列
def fib(n):
if n == 0 or n == 1: # ⬅️ 这是边界墙
return n
return fib(n - 1) + fib(n - 2)
fib(0)
和 fib(1)
是基本情况,不再递归。
从这里开始“往上回溯”,组合出更大的 fib。
例子3:递归打印列表元素
def print_list(lst, i=0):
if i >= len(lst): # ⬅️ 边界墙:到头了
return
print(lst[i])
print_list(lst, i + 1)
最简单情况是:i >= len(lst)
,表示没东西可打印了,停止递归。
通用模板(找边界墙)
def recursive(参数):
if 满足终止条件: # ⬅️ 这是边界墙
return 最简单情况结果
else:
return recursive(更接近终止条件的参数)
记忆口诀:递归三部曲(写的时候就像搭框架)
步骤 | 要做的事 | 举例 |
---|---|---|
第1步 | 写终止条件(边界墙) | if n == 1: return 1 |
第2步 | 写递归逻辑(缩小规模) | factorial(n-1) |
第3步 | 返回本层结果 + 递归结果 | return n * factorial(n-1) |