Python 迭代器和生成器概念

目录


迭代器的介绍

迭代器的定义:

迭代器(Iterator)是 Python 中用于遍历数据集合 的核心机制。它提供了一种统一的方式来访问容器(如列表、字典、文件等)中的元素,而无需关心底层数据结构的具体实现。迭代器的核心特点是按需生成数据,避免一次性加载所有数据到内存。

迭代器适合处理大型数据、无限序列或需要惰性计算的场景。


迭代器的核心概念:

  1. 迭代器协议

    • 一个对象要成为迭代器,必须实现以下两个方法:
      • __iter__():返回迭代器对象本身(通常直接 return self)。
      • __next__():返回下一个元素,若没有更多元素则抛出 StopIteration 异常。
    • Python 的 for 循环、next() 函数等底层都依赖这一协议。
  2. 可迭代对象(Iterable) VS 迭代器(Iterator)

    • 可迭代对象 :实现了 __iter__() 方法,可以返回一个迭代器的对象(如列表、元组、字典)。
    • 迭代器 :实现了 __iter__()__next__() 方法的对象。
    • 所有迭代器都是可迭代对象,但可迭代对象本身不一定是迭代器。

    差异体现在遍历机制:

    • 可迭代对象

      每次调用 iter() 会生成新的迭代器,因此可被多次遍历:

      python 复制代码
      my_list = [1, 2, 3]
      for x in my_list: print(x)  # 输出 1,2,3
      for x in my_list: print(x)  # 再次输出 1,2,3
    • 迭代器

      遍历是一次性的,遍历完成后无法重置:

      python 复制代码
      iterator = iter(my_list)
      for x in iterator: print(x)  # 输出 1,2,3
      for x in iterator: print(x)  # 无输出(迭代器已耗尽)

自定义迭代器

示例 1: 通过类实现迭代器

python 复制代码
class CountUpTo:
    def __init__(self, max_num):
        self.max_num = max_num
        self.current = 0

    def __iter__(self):
        return self  # 返回迭代器本身

    def __next__(self):
        if self.current < self.max_num:
            self.current += 1
            return self.current
        else:
            raise StopIteration  # 终止迭代

# 使用自定义迭代器
counter = CountUpTo(3)
for num in counter:
    print(num)  # 输出 1, 2, 3

示例 2: 通过生成器函数实现(简化版)

生成器函数(使用 yield)是创建迭代器的快捷方式:

python 复制代码
def count_up_to(max_num):
    current = 0
    while current < max_num:
        current += 1
        yield current

# 生成器返回的也是迭代器
for num in count_up_to(3):
    print(num)  # 输出 1, 2, 3

省略的迭代器

写过for循环的都知道,我没用迭代器呀!

用了!只不过是编译器帮你用了。

以下两段代码完全等价:

python 复制代码
# 直接遍历列表
my_list = [1, 2, 3, 4, 5]
for x in my_list:
    print(x)
python 复制代码
# 等价的手动迭代器操作
iterator = iter(my_list)  # 自动调用 __iter__() 获取迭代器
while True:
    try:
        x = next(iterator)  # 自动调用 __next__()
        print(x)
    except StopIteration:
        break  # 自动处理终止

为什么不需要显式写迭代器?

  • 语法糖(Syntactic Sugar):for 循环是 Python 提供的一种简化语法,隐藏了迭代器的创建和异常处理细节。

  • 统一接口:所有可迭代对象(如列表、元组、字典、集合、字符串等)都可以通过 for 循环统一处理,无需关心底层是列表还是其他数据结构。

生产器的介绍

yield是个英文动词,也是名词,含义是生产的意思。

yield 在 Python里就是生成器。

yield的定义:

Python 的 yield 关键字用于定义生成器函数(Generator Function),生成器是一种特殊的迭代器,能够按需生成值并暂停/恢复执行状态。它的核心特性是惰性求值(Lazy Evaluation),适用于处理大数据流、无限序列或需要节省内存的场景。

核心概念:

  1. 生成器函数

    • 使用 yield 代替 return 的函数。
    • 调用生成器函数时,返回一个生成器对象(迭代器),而非直接执行函数体。
    • 生成器通过 next()for 循环逐步执行,每次遇到 yield 时暂停,返回 yield 后的值,并在下次调用时从暂停处继续执行。
  2. 与普通函数的区别

    • 普通函数一次执行完毕,返回一个结果。
    • 生成器函数逐步产生多个值,并在 yield 处保持状态。

return 的区别:

特性 yield return
返回值数量 可多次返回值 仅返回一次
函数状态 暂停并保留状态 终止函数执行
返回类型 生成器对象(迭代器) 直接返回值
内存占用 低(按需生成) 高(一次性生成所有数据)

yield的普通用法

示例 1: 简单生成器

python 复制代码
def simple_generator():
    yield 1
    yield 2
    yield 3

gen = simple_generator()
print(next(gen))  # 输出 1
print(next(gen))  # 输出 2
print(next(gen))  # 输出 3
# 继续调用 next(gen) 会抛出 StopIteration 异常

示例 2:for 循环遍历生成器

python 复制代码
def count_up_to(n):
    i = 0
    while i < n:
        yield i
        i += 1

for num in count_up_to(5):
    print(num)  # 输出 0, 1, 2, 3, 4

yield的高级用法

  1. 通过 send() 传递值

    生成器可以通过 send(value) 接收外部传入的值,赋值给 yield 表达式:

    python 复制代码
    def generator_with_send():
    	value = yield "Ready to receive"
    	yield f"Received: {value}"
    
    gen = generator_with_send()
    print(next(gen))         # 输出 "Ready to receive"
    print(gen.send("Hello")) # 输出 "Received: Hello"
  2. yield from 委托生成

    Python 3.3+ 引入 yield from,用于简化嵌套生成器的操作:

    python 复制代码
    def sub_generator():
    	yield "A"
    	yield "B"
    
    def main_generator():
    	yield from sub_generator()
    	yield "C"
    
    for item in main_generator():
    	print(item)  # 输出 A, B, C
  3. 异常处理

    生成器可以通过 throw() 方法接收异常:

    python 复制代码
    def generator_with_exception(value):
    	try:
    		yield 10 / value
    	except ZeroDivisionError as e:
    		yield "Caught ValueError"
    
    
    gen = generator_with_exception(2)
    print(next(gen))
    
    gen = generator_with_exception(0)
    print(next(gen))

    out:

    复制代码
    5.0
    Caught ValueError

yidle的实际应用案例

  1. 大数据处理

    python 复制代码
    def read_large_file(file_path):
        with open(file_path, "r") as file:
            for line in file:
                yield line.strip()  # 逐行生成,避免一次性加载到内存
    
    for line in read_large_file("data.txt"):
        process(line)
  2. 生成无限序列

    python 复制代码
    def fibonacci():
        a, b = 0, 1
        while True:
            yield a
            a, b = b, a + b
    
    fib = fibonacci()
    print([next(fib) for _ in range(10)])  # 前10个斐波那契数
  3. 协程(Coroutine)

    python 复制代码
    def coroutine():
        while True:
            task = yield
            print(f"Processing: {task}")
    
    worker = coroutine()
    next(worker)       # 启动协程
    worker.send("Task1")  # 输出 "Processing: Task1"
    worker.send("Task2")  # 输出 "Processing: Task2"

    在 Python 中,协程(Coroutine) 是一种可以暂停和恢复执行的函数,它能与调用方进行双向通信(接收和发送数据),常用于实现协作式多任务(非抢占式任务切换)。

    上文提供的代码是一个典型的基于生成器的协程(Generator-based Coroutine)。

总结

yield 是 Python 中实现惰性计算协程 的核心工具,结合 send()throw()close() 等方法,能够构建高效、灵活的数据流和控制流模型。

相关推荐
数据智能老司机1 小时前
精通 Python 设计模式——分布式系统模式
python·设计模式·架构
数据智能老司机2 小时前
精通 Python 设计模式——并发与异步模式
python·设计模式·编程语言
数据智能老司机2 小时前
精通 Python 设计模式——测试模式
python·设计模式·架构
数据智能老司机2 小时前
精通 Python 设计模式——性能模式
python·设计模式·架构
c8i2 小时前
drf初步梳理
python·django
每日AI新事件2 小时前
python的异步函数
python
这里有鱼汤3 小时前
miniQMT下载历史行情数据太慢怎么办?一招提速10倍!
前端·python
databook13 小时前
Manim实现脉冲闪烁特效
后端·python·动效
程序设计实验室13 小时前
2025年了,在 Django 之外,Python Web 框架还能怎么选?
python
倔强青铜三14 小时前
苦练Python第46天:文件写入与上下文管理器
人工智能·python·面试