当前位置: 首页 > 后端技术 > Python

生成器yield关键字详解

时间:2023-03-26 17:47:31 Python

由于yield关键字的原理大家不是很了解,所以今天主要讨论这个话题。如何获得发电机?方法一:推导得到生成器#列表推导list1=[iforiinrange(9)]print(list1)#得到生成器generator=(iforiinrange(9))print(generator)执行结果:[0,1,2,3,4,5,6,7,8]at0x00000151D63DA830>方法二:使用function方法,使用yield获取生成器defgenerator():print('代码开始执行...')whileTrue:response=yield1print('-------------------------------')print('response=',response)g=generator()print(g)executionresult:那么我们现在来说说yield关键字,一起来揭开它的神秘面纱。从这个程序中你看到什么,我们的执行结果是不是一个函数,而是一个生成器,这是我们yield关键字的作用,只要我们在函数中使用了yield关键字,那么它就不再是一个函数,而是发电机。而且,你还可以看到我们的打印语句还没有执行。你有很多问号吗?所以这个原因还是因为它变成发电机的原因造成的。生成器将起到与输入函数类似的阻塞作用。你需要调用它内部的next方法让程序执行一次。再次遇到yield,它也会停止。让我们试一次。defgenerator():print('代码已经开始执行...')whileTrue:response=yield1print('----------------------------')print('response=',response)g=generator()print(g)print(next(g))执行结果:代码开始执行。.......1你现在看到了什么?我们调用next方法后,代码开始正常执行,返回了一个1给我们,证明yield也有类似return的功能。但是从这次执行的结果中,我们是否发现yield关键字下的代码并没有被执行呢?这就是我说的,遇到yield就停下来。如果我们现在再次调用next方法。defgenerator():print('代码开始执行...')whileTrue:response=yield1print('----------------------------')print('response=',response)g=generator()print(g)print(next(g))print(next(g))执行结果:代码开始执行。.......1----------------------------response=None1那么现在你发现了吗,我们打印出三个数据后就停止了再次。但是对比上面的执行结果不难发现,当我们第二次调用next方法时,并没有从上往下执行,而是从上次停止的位置继续执行,也就是我们生成的controller的特性,它会记住你上次停留的地方,下次从这个地方继续执行。嗯,这是一种现象。大家都在看response=None,为什么会出现这样的结果,有同学会疑惑,结果不应该是1吗?怎么可能是无?这里要告诉大家的是,这个1的结果已经被我们的yield返回了,所以这里没有数据,这也是generator的另外一个特点。如果你把这个数据拿出来,那么这个数据在generator里面就不存在了。当你在生成器中取完数据后,就不能再使用了,也就是说生成器只能使用一次。我们再来看第三种现象。最后1从哪里来?由下一个循环的yield返回,这里又yield再次把程序阻塞在这里,知道又调用了next方法或者send方法。那么看到这里,有同学会疑惑,老师,您说的下一个方法我知道,但是send方法是什么?为什么send也可以调用这个生成器呢?别着急,我们先写这段代码。defgenerator():print('代码开始执行...')whileTrue:response=yield1print('------------------------------')print('response=',response)g=generator()print(g)print(next(g))print(next(g))print(g.send(2))执行结果:代码开始执行。.......1--------------------------------响应=无1---------------------------------response=21其实对于我们的send方法,大家应该不难看出,它只是传递了一个值给我们的response,那为什么呢也可以叫做我们的生成器呢?那是因为send也是Generator内部的一个方法,它也封装了next方法,所以我们在调用send方法的时候也可以调用generator。并且可以给yield的赋值对象传一个值。现在大家应该对我们的yield关键字有了深刻的了解了吧?面试官问你,就这样把他打死,你明白了吗?