"不是所有的遍历都叫迭代,但所有的迭代都很优雅" ------ 鲁迅(大概没说过)
📚 目录
- 开场白:为什么要学这玩意儿?
- [第一章:可迭代对象 - 能遍历的都是好对象](#第一章:可迭代对象 - 能遍历的都是好对象 "#%E7%AC%AC%E4%B8%80%E7%AB%A0")
- [第二章:迭代器 - 老实排队的播放器](#第二章:迭代器 - 老实排队的播放器 "#%E7%AC%AC%E4%BA%8C%E7%AB%A0")
- [第三章:生成器 - 按需制作的烤面包机](#第三章:生成器 - 按需制作的烤面包机 "#%E7%AC%AC%E4%B8%89%E7%AB%A0")
- [第四章:实战案例 - 学以致用](#第四章:实战案例 - 学以致用 "#%E7%AC%AC%E5%9B%9B%E7%AB%A0")
- [第五章:性能对比 - 数据说话](#第五章:性能对比 - 数据说话 "#%E7%AC%AC%E4%BA%94%E7%AB%A0")
- [第六章:常见坑点 - 避雷指南](#第六章:常见坑点 - 避雷指南 "#%E7%AC%AC%E5%85%AD%E7%AB%A0")
- 终章:一张图看懂所有
🎬 开场白:为什么要学这玩意儿? {#开场白}
想象一下,你有一个装了100万张照片的硬盘 💾。
方案A(列表方式):把所有照片一次性加载到内存里
- 结果:💥 电脑直接卡死,风扇起飞
方案B(生成器方式):用一张、取一张
- 结果:😌 丝滑流畅,内存稳如老狗
这就是我们今天要学的东西!迭代器和生成器能让你的程序:
- ⚡ 更快(不浪费时间准备不需要的数据)
- 💾 更省内存(按需生产)
- 🎨 代码更优雅(Pythonic!)
📖 第一章:可迭代对象 - 能遍历的都是好对象 {#第一章}
1.1 什么是可迭代对象?
官方定义 :实现了 __iter__()
方法的对象
人话翻译 :能用 for
循环遍历的东西
python
# 这些都是可迭代对象 ✅
my_list = [1, 2, 3, 4, 5]
my_string = "Hello"
my_dict = {"a": 1, "b": 2}
my_tuple = (1, 2, 3)
my_set = {1, 2, 3}
# 这些不是可迭代对象 ❌
my_number = 42
my_function = print
1.2 生活中的例子 🌟
把可迭代对象想象成一个书架 📚:
书架(可迭代对象)
┌─────────────────────┐
│ 📕 书1 │
│ 📗 书2 │
│ 📘 书3 │
│ 📙 书4 │
└─────────────────────┘
你可以一本一本地取书看,但书架本身不会自动给你书,你需要一个"拿书的方法"(迭代器)。
1.3 验证是否可迭代
python
from collections.abc import Iterable
# 检查是否可迭代
print(isinstance([1, 2, 3], Iterable)) # True ✅
print(isinstance("hello", Iterable)) # True ✅
print(isinstance(42, Iterable)) # False ❌
print(isinstance({1, 2, 3}, Iterable)) # True ✅
记忆口诀 :能 for
就能迭代,不能 for
就拉倒 😎
🎵 第二章:迭代器 - 老实排队的播放器 {#第二章}
2.1 什么是迭代器?
官方定义 :同时实现了 __iter__()
和 __next__()
方法的对象
人话翻译:一个记得"我看到哪儿了"的智能书签 🔖
2.2 生活中的例子 🎶
想象你在用音乐播放器听播放列表:
diff
播放列表(迭代器)
┌────────────────────────┐
│ ▶️ 正在播放:歌曲1 │ ← 当前位置(指针)
│ ⏸️ 歌曲2 │
│ ⏸️ 歌曲3 │
│ ⏸️ 歌曲4 │
└────────────────────────┘
操作:
- next() → 播放下一首
- 播完了 → StopIteration(播放列表结束)
2.3 迭代器的工作原理
python
# 创建一个列表(可迭代对象)
my_list = [1, 2, 3]
# 获取迭代器
my_iterator = iter(my_list) # 相当于调用 my_list.__iter__()
# 使用 next() 逐个获取元素
print(next(my_iterator)) # 输出:1
print(next(my_iterator)) # 输出:2
print(next(my_iterator)) # 输出:3
print(next(my_iterator)) # ❌ 报错:StopIteration
流程图:
scss
开始
↓
调用 iter(对象)
↓
获得迭代器 👉 记住当前位置(初始:第一个元素前)
↓
调用 next(迭代器)
↓
返回当前元素 + 指针后移
↓
还有下一个?
├─ 是 → 继续 next()
└─ 否 → 抛出 StopIteration 🛑
2.4 手写一个迭代器 ✍️
让我们自己做一个"倒计时"迭代器:
python
class Countdown:
"""倒计时迭代器 - 像火箭发射倒计时"""
def __init__(self, start):
self.current = start
def __iter__(self):
# 返回迭代器对象本身
return self
def __next__(self):
if self.current <= 0:
raise StopIteration # 🛑 停止信号
self.current -= 1
return self.current + 1
# 使用我们的迭代器
print("🚀 火箭发射倒计时:")
for num in Countdown(5):
print(f"{num}...")
print("🔥 发射!")
# 输出:
# 🚀 火箭发射倒计时:
# 5...
# 4...
# 3...
# 2...
# 1...
# 🔥 发射!
2.5 迭代器 vs 可迭代对象
python
my_list = [1, 2, 3]
my_iter = iter(my_list)
print(iter(my_list) is my_list) # False - 列表不是迭代器
print(iter(my_iter) is my_iter) # True - 迭代器的 iter 返回自己
对比表格:
特性 | 可迭代对象 | 迭代器 |
---|---|---|
有 __iter__() |
✅ | ✅ |
有 __next__() |
❌ | ✅ |
能用 for 循环 |
✅ | ✅ |
可多次遍历 | ✅ | ❌(一次性) |
例子 | list, str, dict | iter(list) |
比喻:
- 可迭代对象 = 🎬 电影DVD(可以反复看)
- 迭代器 = 📺 电视直播(看过就没了)
🍞 第三章:生成器 - 按需制作的烤面包机 {#第三章}
3.1 什么是生成器?
官方定义 :使用 yield
关键字的函数,返回的是生成器对象
人话翻译:一个会"暂停"的函数,需要时才继续干活
3.2 生活中的例子 🥐
传统函数(return)= 一次性烤100个面包:
python
def bake_bread_all():
"""一次性烤完所有面包"""
breads = []
for i in range(100):
breads.append(f"🍞面包{i}")
return breads # 全部烤好才返回
all_breads = bake_bread_all() # 等待烤100个... ⏰💤
print(all_breads[0]) # 我只要第一个啊!
生成器(yield)= 烤一个拿一个:
python
def bake_bread_one_by_one():
"""按需烤面包"""
for i in range(100):
yield f"🍞面包{i}" # 烤一个,暂停,等需要时继续
bakery = bake_bread_one_by_one()
print(next(bakery)) # 🍞面包0 - 立即拿到!
print(next(bakery)) # 🍞面包1 - 现烤现吃!
3.3 yield 的魔法 ✨
yield
就像一个超级暂停键 ⏸️:
lua
函数执行流程:
开始
↓
执行代码...
↓
遇到 yield → ⏸️ 暂停,把值发出去,保存现场
↓
(外部拿到值,做其他事情...)
↓
next() 被调用 → ▶️ 恢复,从暂停处继续
↓
执行代码...
↓
遇到下一个 yield 或函数结束
3.4 第一个生成器 🎓
python
def simple_generator():
print("第一次执行")
yield 1
print("第二次执行")
yield 2
print("第三次执行")
yield 3
print("执行完毕")
gen = simple_generator()
print("=" * 30)
print("调用第1次 next():")
print(next(gen))
# 输出:
# 第一次执行
# 1
print("=" * 30)
print("调用第2次 next():")
print(next(gen))
# 输出:
# 第二次执行
# 2
print("=" * 30)
print("调用第3次 next():")
print(next(gen))
# 输出:
# 第三次执行
# 3
print("=" * 30)
print("调用第4次 next():")
print(next(gen))
# 输出:
# 执行完毕
# StopIteration 错误!
可视化执行流程:
lua
第1次 next():
┌─────────────────┐
│ 函数开始 │
│ print("第一次") │
│ yield 1 ⏸️ │ ← 在这里暂停,返回 1
└─────────────────┘
第2次 next():
┌─────────────────┐
│ yield 1 ▶️ │ ← 从这里恢复
│ print("第二次") │
│ yield 2 ⏸️ │ ← 在这里暂停,返回 2
└─────────────────┘
第3次 next():
┌─────────────────┐
│ yield 2 ▶️ │ ← 从这里恢复
│ print("第三次") │
│ yield 3 ⏸️ │ ← 在这里暂停,返回 3
└─────────────────┘
第4次 next():
┌─────────────────┐
│ yield 3 ▶️ │ ← 从这里恢复
│ print("执行完毕")│
│ 函数结束 🛑 │ ← 抛出 StopIteration
└─────────────────┘
3.5 生成器的经典案例 🌟
案例1:斐波那契数列
python
def fibonacci(n):
"""生成斐波那契数列的前 n 项"""
a, b = 0, 1
count = 0
while count < n:
yield a
a, b = b, a + b
count += 1
# 使用
print("斐波那契数列前10项:")
for num in fibonacci(10):
print(num, end=" ")
# 输出:0 1 1 2 3 5 8 13 21 34
如果用列表方式:
python
def fibonacci_list(n):
"""列表方式 - 占内存"""
result = []
a, b = 0, 1
for _ in range(n):
result.append(a)
a, b = b, a + b
return result
# 问题:如果 n = 1000000,内存直接爆炸 💥
案例2:无限序列生成器 ♾️
python
def infinite_counter():
"""无限计数器"""
num = 0
while True: # 永远循环!
yield num
num += 1
# 使用
counter = infinite_counter()
print(next(counter)) # 0
print(next(counter)) # 1
print(next(counter)) # 2
# ... 可以一直调用下去
# 获取前10个
import itertools
for num in itertools.islice(counter, 10):
print(num, end=" ")
# 输出:3 4 5 6 7 8 9 10 11 12
为什么能无限? 因为生成器是惰性的,不会一次性生成所有数字!
案例3:读取大文件 📄
python
def read_large_file(file_path):
"""逐行读取大文件 - 不怕文件多大"""
with open(file_path, 'r', encoding='utf-8') as f:
for line in f:
yield line.strip()
# 使用 - 即使文件有10GB,内存占用也很小
for line in read_large_file('huge_log.txt'):
if 'ERROR' in line:
print(line)
break # 找到就停止,不用读完整个文件
对比传统方式:
python
# ❌ 危险方式 - 小文件还好,大文件直接OOM
with open('huge_log.txt', 'r') as f:
lines = f.readlines() # 全部读入内存!💥
for line in lines:
if 'ERROR' in line:
print(line)
break
3.6 生成器表达式 🚀
类似列表推导式,但更省内存:
python
# 列表推导式 - 立即创建整个列表
squares_list = [x**2 for x in range(1000000)] # 占用大量内存 💾
# 生成器表达式 - 按需生成
squares_gen = (x**2 for x in range(1000000)) # 几乎不占内存 ✨
print(type(squares_list)) # <class 'list'>
print(type(squares_gen)) # <class 'generator'>
# 获取第一个值
print(next(squares_gen)) # 0
print(next(squares_gen)) # 1
print(next(squares_gen)) # 4
语法对比:
类型 | 语法 | 内存占用 |
---|---|---|
列表推导式 | [表达式 for 变量 in 可迭代对象] |
立即占用 |
生成器表达式 | (表达式 for 变量 in 可迭代对象) |
惰性占用 |
3.7 yield from - 生成器的传送门 🚪
python
def generator1():
yield 1
yield 2
def generator2():
yield 3
yield 4
# 笨办法:手动循环
def combined_old():
for item in generator1():
yield item
for item in generator2():
yield item
# 优雅方式:yield from
def combined_new():
yield from generator1()
yield from generator2()
# 使用
for num in combined_new():
print(num, end=" ")
# 输出:1 2 3 4
生活比喻:
yield
= 自己一个一个递东西给别人yield from
= 让另一个人直接递东西给别人(委托)
🎯 第四章:实战案例 - 学以致用 {#第四章}
4.1 数据流水线 🏭
python
def read_data():
"""步骤1:读取原始数据"""
data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
for item in data:
yield item
def filter_even(numbers):
"""步骤2:过滤出偶数"""
for num in numbers:
if num % 2 == 0:
yield num
def square(numbers):
"""步骤3:平方"""
for num in numbers:
yield num ** 2
def add_prefix(numbers):
"""步骤4:添加前缀"""
for num in numbers:
yield f"数字-{num}"
# 组装流水线 🔧
pipeline = add_prefix(square(filter_even(read_data())))
# 执行
print("流水线输出:")
for result in pipeline:
print(result)
# 输出:
# 数字-4
# 数字-16
# 数字-36
# 数字-64
# 数字-100
流程图:
scss
[1,2,3,4,5...]
↓ read_data()
[1,2,3,4,5...]
↓ filter_even()
[2,4,6,8,10]
↓ square()
[4,16,36,64,100]
↓ add_prefix()
["数字-4", "数字-16", ...]
优势:每一步都是惰性的,内存占用极小!
4.2 批量处理 📦
python
def batch_processor(data, batch_size):
"""将数据分批处理"""
batch = []
for item in data:
batch.append(item)
if len(batch) == batch_size:
yield batch
batch = []
# 处理剩余数据
if batch:
yield batch
# 使用
data = range(1, 13) # 1到12
for batch in batch_processor(data, 5):
print(f"处理批次:{batch}")
# 输出:
# 处理批次:[1, 2, 3, 4, 5]
# 处理批次:[6, 7, 8, 9, 10]
# 处理批次:[11, 12]
4.3 滑动窗口 🪟
python
def sliding_window(sequence, window_size):
"""滑动窗口生成器"""
it = iter(sequence)
window = []
# 填充初始窗口
for _ in range(window_size):
try:
window.append(next(it))
except StopIteration:
return
yield tuple(window)
# 滑动窗口
for item in it:
window = window[1:] + [item]
yield tuple(window)
# 使用 - 计算移动平均
prices = [10, 12, 11, 15, 13, 14, 16, 18, 17]
print("3日移动平均:")
for window in sliding_window(prices, 3):
avg = sum(window) / len(window)
print(f"{window} → 平均: {avg:.2f}")
# 输出:
# (10, 12, 11) → 平均: 11.00
# (12, 11, 15) → 平均: 12.67
# (11, 15, 13) → 平均: 13.00
# ...
4.4 树遍历 🌳
python
class TreeNode:
def __init__(self, value, children=None):
self.value = value
self.children = children or []
def traverse_tree(node):
"""深度优先遍历树"""
yield node.value
for child in node.children:
yield from traverse_tree(child)
# 构建树
tree = TreeNode("根", [
TreeNode("子1", [
TreeNode("孙1-1"),
TreeNode("孙1-2")
]),
TreeNode("子2", [
TreeNode("孙2-1")
])
])
# 遍历
print("树遍历结果:")
for value in traverse_tree(tree):
print(value)
# 输出:
# 根
# 子1
# 孙1-1
# 孙1-2
# 子2
# 孙2-1
⚡ 第五章:性能对比 - 数据说话 {#第五章}
5.1 内存占用对比
python
import sys
# 列表方式
list_data = [x for x in range(1000000)]
print(f"列表内存占用: {sys.getsizeof(list_data) / 1024 / 1024:.2f} MB")
# 输出:列表内存占用: 8.39 MB
# 生成器方式
gen_data = (x for x in range(1000000))
print(f"生成器内存占用: {sys.getsizeof(gen_data) / 1024:.2f} KB")
# 输出:生成器内存占用: 0.11 KB
# 差距:约 76,000 倍!😱
可视化对比:
makefile
内存占用:
列表: [████████████████████████████] 8.39 MB
生成器: [█] 0.11 KB
差距就像:
列表: 🐘 大象
生成器: 🐜 蚂蚁
5.2 创建速度对比
python
import time
# 测试列表创建
start = time.time()
list_obj = [x**2 for x in range(1000000)]
list_time = time.time() - start
print(f"列表创建时间: {list_time:.4f} 秒")
# 测试生成器创建
start = time.time()
gen_obj = (x**2 for x in range(1000000))
gen_time = time.time() - start
print(f"生成器创建时间: {gen_time:.6f} 秒")
print(f"速度差距: {list_time / gen_time:.0f} 倍")
# 示例输出:
# 列表创建时间: 0.0856 秒
# 生成器创建时间: 0.000002 秒
# 速度差距: 42800 倍 🚀
5.3 什么时候用什么?
python
# ✅ 使用列表的场景
situations_for_list = [
"需要多次遍历数据",
"需要索引访问(list[5])",
"需要切片操作(list[2:5])",
"数据量小(< 10000)",
"需要 len() 获取长度",
]
# ✅ 使用生成器的场景
situations_for_generator = [
"数据量很大",
"只需要遍历一次",
"无限序列",
"流式处理数据",
"节省内存是首要任务",
"数据处理管道",
]
决策树:
markdown
需要处理数据
↓
数据量大吗?(> 10万)
├─ 是 → 需要多次遍历吗?
│ ├─ 是 → 考虑使用列表(但注意内存)
│ └─ 否 → 用生成器 ✅
│
└─ 否 → 需要索引访问吗?
├─ 是 → 用列表 ✅
└─ 否 → 两者都行,生成器更优雅
🚨 第六章:常见坑点 - 避雷指南 {#第六章}
坑点1:生成器只能用一次 ⚠️
python
gen = (x for x in range(5))
# 第一次遍历
print("第一次遍历:")
for num in gen:
print(num, end=" ")
print()
# 输出:0 1 2 3 4
# 第二次遍历
print("第二次遍历:")
for num in gen:
print(num, end=" ")
print()
# 输出:(什么都没有!)😱
# 解释:生成器已经耗尽了!
解决方案:
python
# 方案1:重新创建生成器
def get_numbers():
return (x for x in range(5))
gen1 = get_numbers()
gen2 = get_numbers() # 创建新的
# 方案2:如果需要多次使用,用列表
numbers = list(get_numbers())
坑点2:忘记处理 StopIteration
python
gen = (x for x in range(3))
# ❌ 危险做法
try:
print(next(gen)) # 0
print(next(gen)) # 1
print(next(gen)) # 2
print(next(gen)) # 💥 StopIteration!
except StopIteration:
print("生成器已经结束啦!")
# ✅ 推荐做法:使用 for 循环(自动处理 StopIteration)
gen = (x for x in range(3))
for num in gen:
print(num)
坑点3:生成器中的循环变量陷阱
python
# ❌ 错误方式
generators = [lambda: x for x in range(5)]
print([g() for g in generators])
# 输出:[4, 4, 4, 4, 4] 😱 全是4!
# ✅ 正确方式
generators = [lambda x=x: x for x in range(5)]
print([g() for g in generators])
# 输出:[0, 1, 2, 3, 4] ✅
坑点4:生成器不支持 len()
python
gen = (x for x in range(100))
# ❌ 这样不行
try:
print(len(gen))
except TypeError as e:
print(f"错误:{e}")
# 输出:错误:object of type 'generator' has no len()
# ✅ 如果需要长度,转换成列表
gen_list = list(gen)
print(len(gen_list)) # 100
# 注意:转换后就失去了生成器的优势!
坑点5:生成器内部异常处理
python
def risky_generator():
try:
yield 1
yield 2
raise ValueError("出错了!")
yield 3 # 永远不会执行
except ValueError as e:
print(f"捕获异常:{e}")
yield 999 # 可以在异常后继续 yield
# 使用
gen = risky_generator()
print(next(gen)) # 1
print(next(gen)) # 2
print(next(gen)) # 捕获异常:出错了!然后输出 999
print(next(gen)) # StopIteration
🎓 终章:一张图看懂所有 {#终章}
完整知识体系图
scss
Python 迭代器和生成器生态系统
═════════════════════════════════
可迭代对象 (Iterable)
实现 __iter__()
│
┌───────────────┼───────────────┐
│ │ │
列表/元组 字符串/字典 自定义对象
[1,2,3] "hello" MyClass
│ │ │
└───────────────┼───────────────┘
│
调用 iter()
↓
迭代器 (Iterator)
实现 __iter__() + __next__()
│
┌───────────────┼───────────────┐
│ │ │
自定义迭代器 生成器函数 生成器表达式
class MyIter def gen(): (x for x in ...)
yield x
│
┌───────────────┼───────────────┐
│ │ │
yield yield from 无限生成器
单个值 委托 while True
│
┌───────────────┴───────────────┐
│ │
惰性求值 节省内存
需要时才计算 按需生产
核心概念速查表
概念 | 关键方法 | 特点 | 比喻 |
---|---|---|---|
可迭代对象 | __iter__() |
可以被遍历 | 📚 书架 |
迭代器 | __iter__() __next__() |
记住位置,一次性 | 🎵 播放器 |
生成器函数 | yield |
惰性计算,暂停恢复 | 🍞 烤面包机 |
生成器表达式 | (x for x in ...) |
紧凑语法,省内存 | 🎯 快捷方式 |
选择指南 📊
python
# 问自己三个问题:
# 1. 数据量大吗?
if 数据量 > 100000:
首选生成器 = True
else:
首选列表 = True
# 2. 需要多次遍历吗?
if 需要多次遍历:
用列表 = True
else:
用生成器 = True
# 3. 需要索引访问吗?
if 需要索引访问:
必须用列表 = True
else:
生成器更优雅 = True
性能对比总结 📈
场景:处理100万条数据
┌─────────────┬──────────┬─────────┬──────────┐
│ 方案 │ 内存占用 │ 创建速度│ 灵活性 │
├─────────────┼──────────┼─────────┼──────────┤
│ 列表 │ 💾💾💾 │ 🐌 慢 │ ⭐⭐⭐ │
│ 迭代器 │ 💾 │ 🚀 快 │ ⭐⭐ │
│ 生成器 │ 💾 │ ⚡ 超快 │ ⭐⭐⭐ │
└─────────────┴──────────┴─────────┴──────────┘
结论:生成器 = 性能之王 👑
最佳实践 ✨
python
# ✅ DO - 推荐做法
def good_practices():
# 1. 处理大文件用生成器
def read_file(path):
with open(path) as f:
for line in f:
yield line.strip()
# 2. 数据管道用生成器
def pipeline():
data = get_data()
filtered = (x for x in data if x > 0)
processed = (x * 2 for x in filtered)
return processed
# 3. 无限序列用生成器
def counter():
n = 0
while True:
yield n
n += 1
# 4. 需要多次访问用列表
important_data = list(get_data()) # 明确转换
# ❌ DON'T - 避免这样做
def bad_practices():
# 1. 不要对生成器多次遍历
gen = (x for x in range(10))
list(gen) # 第一次
list(gen) # 💥 第二次为空!
# 2. 不要在内存敏感场景用列表
huge_list = [x for x in range(10000000)] # 💥 内存爆炸
# 3. 不要混淆生成器和列表语法
not_a_gen = [x for x in range(10)] # 这是列表!
is_a_gen = (x for x in range(10)) # 这才是生成器
🎉 结语:你已经掌握了!
关键要点回顾 📝
- 可迭代对象 :能用
for
循环的东西 - 迭代器:记住位置的"播放器"
- 生成器 :会"暂停"的函数,用
yield
- 核心优势:省内存、快速、优雅
记忆口诀 🎵
arduino
可迭代能 for,迭代器记路
生成器 yield,惰性最优秀
列表要空间,生成器省内存
数据流水线,生成器是神
进阶学习资源 📚
- 协程(Coroutines)- 生成器的高级用法
itertools
模块 - 迭代器工具箱- 异步生成器(async/await)
- 生成器的 send() 和 close() 方法
最后的最后 🌟
记住这句话:
"能用生成器的地方就用生成器,除非你有充分的理由不用。"
现在,去写优雅的 Python 代码吧!💪
附录:快速参考代码 💻
python
# ============= 快速参考 =============
# 1. 创建迭代器
my_list = [1, 2, 3]
my_iter = iter(my_list)
print(next(my_iter)) # 1
# 2. 创建生成器函数
def my_gen():
yield 1
yield 2
yield 3
# 3. 创建生成器表达式
gen_exp = (x**2 for x in range(10))
# 4. yield from
def delegator():
yield from my_gen()
yield from another_gen()
# 5. 检查类型
from collections.abc import Iterable, Iterator
isinstance([1, 2], Iterable) # True
isinstance([1, 2], Iterator) # False
isinstance(iter([1, 2]), Iterator) # True
# 6. 生成器用于大文件
def read_large_file(path):
with open(path) as f:
for line in f:
yield line
# 7. 无限生成器
def infinite():
n = 0
while True:
yield n
n += 1
# 8. 列表 vs 生成器
list_comp = [x for x in range(1000)] # 列表推导
gen_exp = (x for x in range(1000)) # 生成器表达式
# 9. 数据管道
pipeline = (
process(item)
for item in data
if filter(item)
)
# 10. 批处理
def batch(iterable, n):
batch = []
for item in iterable:
batch.append(item)
if len(batch) == n:
yield batch
batch = []
if batch:
yield batch
🎊 恭喜你完成学习!🎊
如果觉得有帮助,请给个 ⭐ Star!
Made with ❤️ and ☕
最后更新:2025年10月