Python基础概念:生成器和迭代器
关于可迭代对象
Python最基础的容器类数据结构如数组、元组,可以更抽象地描述为“可迭代对象”。所谓可迭代对象,可以通俗理解为可通过for循环迭代的对象,大部份内置容器(list、str、dict、tuple、set)都是可迭代对象。追究其技术细节,是因为这些容器实现了可迭代的协议(__iter__方法),从而“可迭代”。
__iter__方法返回一个迭代器对象。
if __name__ == "__main__":
test_list = ["hello", "world"]
itera = iter(test_list)
print(next(itera))
print(next(itera))
#
# Output:
# hello
# world
迭代器与可迭代对象的区别
迭代器是实现了__iter__和__next__方法的对象,通过next方法可以获取迭代器中的元素,直到没有更多元素为止(抛出StopIteration异常)。通过iter()方法可从可迭代对象得到一个迭代器。
简单来说:
可迭代对象提供了创建迭代器的功能,主要职责是返回一个迭代器对象
迭代器负责实际的迭代过程:逐个返回元素
生成器与迭代器的区别与联系
生成器和迭代器都是用于逐个生成值,支持遍历且由于不需要保存整个序列的数据对内存资源需求较少,适合处理大规模数据集。
生成器是一种特殊的迭代器,不用显式地实现__iter__和__next__方法,只需要通过函数和yield关键字即可轻松便捷地定义一个迭代器。对于复杂逻辑,生成器可能比显式实现__iter__和__next__方法的迭代器更容易维护。
yield关键字的魔力:冻结函数状态并返回值给调用者,直到下一次调用再从上次离开的地方开始执行。
生成器的独特之处
不仅可以产生值,还可以接受调用者从外部传来的值。
.send方法允许调用者向生成器发送数据
使用 .send()
方法的方式
- 初始调用时,应该先调用一次
next()
或者.send(None)
来启动生成器,直到第一个yield
语句被执行。 - 之后,可以通过
.send(value)
向生成器发送数据,这个值将成为当前yield
表达式的返回值。 - 每次
.send()
调用后,生成器将继续执行直到下一个yield
,此时它可以再次产出一个新的值或者等待新的.send()
输入。
代码案例:使用生成器和.send方法实现数值累加:
def accumulater():
total = 0
while True:
x = yield total
if x is None:
break
total += x
print(total, x)
if __name__ == "__main__":
s = accumulater()
s.send(None) # # next(s)
s.send(1)
s.send(20)
s.send(30)