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)
CoolCats
CoolCats
理学学士

我的研究兴趣是时空数据分析、知识图谱、自然语言处理与服务端开发