目录
- 迭代器的介绍
- 自定义迭代器
- 省略的迭代器
- 生产器的介绍
- yield的普通用法
- yield的高级用法
- yidle的实际应用案例
- 总结
迭代器的介绍
迭代器的定义:
迭代器(Iterator)是 Python 中用于遍历数据集合的核心机制。它提供了一种统一的方式来访问容器(如列表、字典、文件等)中的元素,而无需关心底层数据结构的具体实现。迭代器的核心特点是按需生成数据,避免一次性加载所有数据到内存。
迭代器适合处理大型数据、无限序列或需要惰性计算的场景。
迭代器的核心概念:
- 迭代器协议:
- 一个对象要成为迭代器,必须实现以下两个方法:
- __iter__():返回迭代器对象本身(通常直接 return self)。
- __next__():返回下一个元素,若没有更多元素则抛出 StopIteration 异常。
- Python 的 for 循环、next() 函数等底层都依赖这一协议。
- 可迭代对象(Iterable) VS 迭代器(Iterator):
- 可迭代对象:实现了 __iter__() 方法,可以返回一个迭代器的对象(如列表、元组、字典)。
- 迭代器:实现了 __iter__() 和 __next__() 方法的对象。
- 所有迭代器都是可迭代对象,但可迭代对象本身不一定是迭代器。
差异体现在遍历机制:
- 可迭代对象:
每次调用 iter() 会生成新的迭代器,因此可被多次遍历:- 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
复制代码 - 迭代器:
遍历是一次性的,遍历完成后无法重置:- iterator = iter(my_list)
- for x in iterator: print(x) # 输出 1,2,3
- for x in iterator: print(x) # 无输出(迭代器已耗尽)
复制代码
自定义迭代器
示例 1: 通过类实现迭代器- 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)是创建迭代器的快捷方式:- 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循环的都知道,我没用迭代器呀!
用了!只不过是编译器帮你用了。
以下两段代码完全等价:- # 直接遍历列表
- my_list = [1, 2, 3, 4, 5]
- for x in my_list:
- print(x)
复制代码- # 等价的手动迭代器操作
- 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),适用于处理大数据流、无限序列或需要节省内存的场景。
核心概念:
- 生成器函数:
- 使用 yield 代替 return 的函数。
- 调用生成器函数时,返回一个生成器对象(迭代器),而非直接执行函数体。
- 生成器通过 next() 或 for 循环逐步执行,每次遇到 yield 时暂停,返回 yield 后的值,并在下次调用时从暂停处继续执行。
- 与普通函数的区别:
- 普通函数一次执行完毕,返回一个结果。
- 生成器函数逐步产生多个值,并在 yield 处保持状态。
与 return 的区别:
特性yieldreturn返回值数量可多次返回值仅返回一次函数状态暂停并保留状态终止函数执行返回类型生成器对象(迭代器)直接返回值内存占用低(按需生成)高(一次性生成所有数据)yield的普通用法
示例 1: 简单生成器- 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 循环遍历生成器- 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的高级用法
- 通过 send() 传递值
生成器可以通过 send(value) 接收外部传入的值,赋值给 yield 表达式:- 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"
复制代码 - yield from 委托生成
Python 3.3+ 引入 yield from,用于简化嵌套生成器的操作:- 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
复制代码 - 异常处理
生成器可以通过 throw() 方法接收异常:- 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: yidle的实际应用案例
- 大数据处理:
- 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)
复制代码 - 生成无限序列:
- 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个斐波那契数
复制代码 - 协程(Coroutine):
- 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() 等方法,能够构建高效、灵活的数据流和控制流模型。
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |