🎯 Python迭代器与生成器:从入门到"哦原来如此!"

"不是所有的遍历都叫迭代,但所有的迭代都很优雅" ------ 鲁迅(大概没说过)

📚 目录

  • 开场白:为什么要学这玩意儿?
  • [第一章:可迭代对象 - 能遍历的都是好对象](#第一章:可迭代对象 - 能遍历的都是好对象 "#%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))   # 这才是生成器

🎉 结语:你已经掌握了!

关键要点回顾 📝

  1. 可迭代对象 :能用 for 循环的东西
  2. 迭代器:记住位置的"播放器"
  3. 生成器 :会"暂停"的函数,用 yield
  4. 核心优势:省内存、快速、优雅

记忆口诀 🎵

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月

相关推荐
开心-开心急了3 小时前
PySide6 使用搜索引擎搜索 多类实现 更新1次
python·pyqt·pyside
万粉变现经纪人3 小时前
如何解决 pip install -r requirements.txt 子目录可编辑安装缺少 pyproject.toml 问题
开发语言·python·scrapy·beautifulsoup·scikit-learn·matplotlib·pip
Blossom.1183 小时前
把 AI“缝”进布里:生成式编织神经网络让布料自带摄像头
人工智能·python·单片机·深度学习·神经网络·目标检测·机器学习
滑水滑成滑头3 小时前
**点云处理:发散创新,探索前沿技术**随着科技的飞速发展,点云处理技术在计算机视觉、自动驾驶、虚拟现实等领域的应用愈发广
java·python·科技·计算机视觉·自动驾驶
gc_22994 小时前
学习Python中Selenium模块的基本用法(19:操作下拉框)
python·selenium
我的xiaodoujiao4 小时前
使用 Python 语言 从 0 到 1 搭建完整 Web UI自动化测试学习系列 19--测试框架Pytest基础 3--前后置操作应用
python·学习·测试工具·pytest
计算衎4 小时前
基于Python实现CANoe和UDE交互通信工具实现,CAPL脚本通过python交互工具与UDE进行通信和调用UDE的组件获取UDE返回值。
python·capl·canoe·ude·nm_oncan
报错小能手4 小时前
python(入门)map内置函数及import模块导入,as别名
开发语言·人工智能·python