从0开始转入Ai应用层,从python学起第十三天
一、三器一闭总览
"三器一闭"是Python中四个核心高级特性:
- 闭包:函数 + 环境,是装饰器的基础
- 装饰器:基于闭包的进阶应用
- 迭代器:实现了
__iter__和__next__方法的对象 - 生成器:特殊的迭代器,使用
yield关键字
它们的关系:
闭包 → 装饰器(基于闭包)
迭代器 → 生成器(特殊迭代器)
二、什么是迭代器
迭代器是一种设计模式,能够顺序访问集合中的元素,无需暴露集合的内部结构。通俗理解:迭代器是一个"指哪打哪"的智能指针,你只需要告诉它"给我下一个元素",它就会按顺序返回。
核心协议:
__iter__():返回迭代器对象本身__next__():返回下一个元素,没有更多元素时抛出StopIteration异常
三、创建迭代器的三种方式
方法1:使用 iter() 函数
# 将可迭代对象转换为迭代器
list1 = [1, 2, 3, 4, 5]
iter1 = iter(list1)
# 用 next() 逐个获取元素
print(next(iter1)) # 1
print(next(iter1)) # 2
print(next(iter1)) # 3
# 元素取完后抛出 StopIteration 异常
方法2:for循环遍历迭代器
for循环本质上就是不断调用 next(),直到捕获 StopIteration 异常后自动停止:
list1 = [1, 2, 3, 4, 5]
iter1 = iter(list1)
for i in iter1:
print(i) # 1 2 3 4 5
方法3:自定义迭代器类
需要定义一个类,实现 __iter__() 和 __next__() 方法:
class MyIter:
def __init__(self):
self.a = 1 # 初始化计数器
def __iter__(self):
return self # 返回迭代器对象本身
def __next__(self):
if self.a <= 5: # 设置停止条件
x = self.a
self.a += 1
return x
else:
raise StopIteration # 抛出异常,结束迭代
# 使用自定义迭代器
myiter = MyIter()
for i in myiter:
print(i) # 1 2 3 4 5
四、可迭代对象 vs 迭代器
重要区别:
- 可迭代对象:实现了
__iter__()方法的对象(如列表、元组、字典) - 迭代器:实现了
__iter__()和__next__()方法的对象
# 可迭代对象(但不是迭代器)
class MyIterable:
def __init__(self, data):
self.data = data
def __iter__(self):
return iter(self.data) # 返回一个新的迭代器
# 迭代器(同时实现了 __iter__ 和 __next__)
class MyIterator:
def __init__(self, data):
self.data = data
def __iter__(self):
return self
def __next__(self):
if self.data <= 0:
raise StopIteration
else:
value = self.data
self.data -= 1
return value
for num in MyIterator(5):
print(num) # 5 4 3 2 1
一句话区分:所有的迭代器都是可迭代对象,但并非所有可迭代对象都是迭代器。列表是可迭代对象但不是迭代器,iter(列表) 返回的才是迭代器。
五、内置迭代工具
iter() 和 next() 函数:
list1 = [1, 2, 3, 4, 5]
iter1 = iter(list1)
print(next(iter1)) # 1
print(next(iter1)) # 2
itertools 模块(提供更多迭代工具):
import itertools
# 无限计数迭代器
for i in itertools.count(10):
print(i) # 10, 11, 12, ... 无限循环
# 循环迭代器
for i in itertools.cycle([1, 2, 3]):
print(i) # 1, 2, 3, 1, 2, 3, ... 无限循环
六、迭代器的优势
- 惰性计算:只在需要时生成值,节省内存
- 无限序列:可以表示无限序列(如自然数序列)
- 统一接口:为不同的数据结构提供统一的遍历接口
- 状态保持:自动记住遍历位置
七、生成器
生成器是简化版的迭代器,用 yield 关键字替代 return,Python会自动为其生成 __iter__() 和 __next__() 方法。
核心特征:
- 执行到
yield时暂停,保留当前状态 - 下次调用
next()时从暂停处继续执行 - 执行完毕后自动抛出
StopIteration异常
普通函数 vs 生成器函数:
# 普通函数:一次性返回所有数据
def run():
return [1, 2, 3, 4, 5]
result = run() # 返回完整列表 [1, 2, 3, 4, 5]
# 生成器函数:逐个返回数据
def run2():
yield 1
yield 2
yield 3
yield 4
yield 5
gen = run2() # 返回生成器对象
print(next(gen)) # 1
print(next(gen)) # 2
八、创建生成器的三种方法
方法1:生成器函数(最常用)
使用 yield 关键字的函数:
def count_up_to(n):
"""生成从1到n的数字"""
count = 1
while count <= n:
yield count
count += 1
counter = count_up_to(5)
print(list(counter)) # [1, 2, 3, 4, 5]
# 直接遍历
for num in count_up_to(5):
print(num) # 1 2 3 4 5
方法2:生成器表达式
类似列表推导式,但使用圆括号:
nums = (x * x for x in range(5))
print(nums) # 生成器对象
print(list(nums)) # [0, 1, 4, 9, 16]
方法3:使用 yield from(Python 3.3+)
从另一个可迭代对象中生成值:
def count_up_to(n):
yield from range(n) # 从range中逐个生成值
print(list(count_up_to(5))) # [0, 1, 2, 3, 4]
九、生成器的工作原理
状态保持:生成器函数在 yield 处暂停执行,并保存所有局部变量状态:
def get_name(n):
for i in range(n):
yield "张三" + str(i)
gen = get_name(5)
print(next(gen)) # 张三0(暂停在yield处)
print(next(gen)) # 张三1(从上次暂停处继续)
print(next(gen)) # 张三2
send() 方法:向生成器发送值:
def my_iter(n):
for i in range(n):
name = yield "张三" + str(i)
print("接收到的值:", name)
gen = my_iter(5)
print(next(gen)) # 张三0(启动生成器)
print(gen.send(10)) # 接收到的值: 10 → 张三1
gen.close() # 关闭生成器
throw() 和 close() 方法:
throw():向生成器内部抛出异常close():关闭生成器,后续调用next()会抛出StopIteration
十、生成器的实战场景
场景1:逐行读取大型文件(节省内存):
def read_file(filename):
with open(filename, "r", encoding="utf-8") as f:
for line in f:
yield line.strip() # 逐行返回
# 使用生成器读取文件
lines = read_file("jk.txt")
for line in lines:
print(line)
场景2:生成无限序列(无需担心内存溢出):
def infinite_counter(start):
while True:
yield start
start += 1
num = infinite_counter(1)
for _ in range(5):
print(next(num)) # 1, 2, 3, 4, 5
十一、生成器 vs 普通迭代器
| 特性 | 普通迭代器(自定义类) | 生成器 |
|---|---|---|
| 实现方式 | 手动写 __iter__ + __next__ |
用 yield 关键字,自动生成 |
| 代码量 | 多(需定义类、处理状态) | 少(函数/表达式即可) |
| 状态管理 | 手动维护(如index变量) | 自动维护(Python保存执行状态) |
| 开发效率 | 低 | 高(极简写法) |
| 功能 | 灵活(可自定义复杂逻辑) | 简洁(适合常规迭代场景) |
一句话总结:生成器 = 迭代器的"懒人写法",用最少的代码实现迭代器的核心功能。
今日核心总结
-
迭代器:
- 实现了
__iter__()和__next__()方法的对象 - 用
iter()将可迭代对象转为迭代器 - 用
next()逐个获取元素,取完抛出StopIteration - 惰性计算,节省内存,自动记住遍历位置
- 实现了
-
可迭代对象 vs 迭代器:
- 可迭代对象:有
__iter__()(如列表、字典) - 迭代器:有
__iter__()和__next__()(如iter(list)) - 所有迭代器都是可迭代对象,反之不一定
- 可迭代对象:有
-
生成器:
- 简化版迭代器,用
yield关键字 - 三种创建方式:生成器函数、生成器表达式、
yield from - 状态自动保存,执行到
yield暂停,下次next()继续 - 适合处理大数据、超大文件、无限序列
- 简化版迭代器,用
-
三器一闭关系:
- 闭包是装饰器的基础
- 生成器是迭代器的简化版
- 生成器表达式是列表推导式的惰性版本
注:已经使用DeepSeek进行整理精简核心内容,些许不理解的配合个人笔记进行理解。
更多推荐


所有评论(0)