python笔记 生成器

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第6天,点击查看活动详情

0 环境

  • 编辑器:idea或vscode
  • 系统版本:windows10
  • python版本:3.9.6

1 前言

前面简单介绍了return和yield混用在一起,会生发生什么,下面继续。

2 yield的原理

先定义个函数,它里面有两个yield,一个return。我们脑海中的结果,正常会认为最后的return 3会被调用,让我们debug一步步的debug下,验证一下,到底我们的猜想对不对。

def gen2():
    print("1")
    yield 1
    print(2)
    yield 2
    print(3)
    return 3

if __name__ == '__main__':
    result2 = gen2()
    print(result2)
    print(next(result2))
    print(next(result2))
    print(next(result2))

可以看到,这里的gen2是个生成器。 image.png

现在执行第一个next方法,进入了print("1")。控制台打印结果是1。 image.png

image.png

继续执行,进入到了yield 1。 image.png 在继续执行,yield 1执行完后,回到__main__里,第一个next得到yield弹出1的值,控制台也可以看到,现在准备执行第二个next方法了。 image.png

现在执行第二个next方法,再次进入到了gen2的函数中,它不是指向第一个print("1"),而是继续执行yield 1下一行的代码,print("2"),也就说明,之前所讲的,保护现场是很形象的。 image.png

继续往下执行,得到了print的打印结果2。 image.png 再继续往下执行,回到了__main__下的第三个next方法的位置,并得到了yield弹出值2。 image.png 继续执行,再次进入到了gen2函数中,指向print("3")这行代码。 image.png 继续执行,得到3的打印值。 image.png 继续执行,得到报错StopIteration: 3。 image.png

3 总结

如上有两个yield和一个return时,每当调用一次next方法时,进入到函数内,并执行了该yield,它就会停止执行(不会往下执行,并且停在这里),然后打印出这次yield弹出的值,当第二个next方法执行了,进入函数中时,并代码并不是从头开始执行,而是从上次yield的位置为标记,从它的下一行代码开始执行,也就说明了现成是被保留下来了,当再次执行next方法时,函数内已经没有可执行的yield关键字了,会抛出异常,它的报错StopIteration 3。这里抛出的异常值是不是,返回值呢。假如再次next方法执行。规律就是,生成器函数函数,它带有yield语句的函数,生成器函数返回值是生成器。

猜你喜欢

转载自juejin.im/post/7126718930227298317