python yield

系统 1345 0

yield

带有 yield 的函数在 Python 中被称之为 generator(生成器),生成器(generator)能够迭代的关键是它有一个next()方法,工作原理就是通过重复调用next()方法,直到捕获一个异常。

生成器与迭代器会在另一篇文章介绍

yield 是一个类似 return的关键字,迭代一次遇到yield时就返回yield后面的值。重点是:下一次迭代时,从上一次迭代遇到的yield后面的代码开始执行。

简要理解:yield就是 return 返回一个值,并且记住这个返回的位置,下次迭代就从这个位置后开始。

首先先举例了解下yield的用法

            
              def
            
            
               myyield():
    
            
            
              print
            
            (
            
              '
            
            
              start program
            
            
              '
            
            
              )
    
            
            
              while
            
            
               True:
        res 
            
            = 
            
              yield
            
            
              '
            
            
              yes
            
            
              '
            
            
              print
            
            (
            
              '
            
            
              resprint:
            
            
              '
            
            
              ,res)


test
            
            =myyield()
          

运行这段代码会怎么样呢?

            C:\Users\11573\AppData\Local\Programs\Python\Python36\python.exe D:/pythonwork/socket/
            
              test.py

Process finished with exit code 0
            
          

奇怪,竟然什么都没有打印,按理说至少会打印一个 start program 才对,但是运行过后什么都没有,这是为什么呢?

next()

程序开始执行以后,因为myyield函数中有yield关键字,所以myyield函数并不会真的执行,而是先得到一个生成器test(相当于一个对象),直到我们调用next方法,myyield函数正式开始执行,先执行myyield函数中的print方法,然后进入while循环

我们修改下代码

            
              def
            
            
               myyield():
    
            
            
              print
            
            (
            
              '
            
            
              starting program
            
            
              '
            
            
              )
    
            
            
              while
            
            
               True:
        res 
            
            = 
            
              yield
            
            
              '
            
            
              yes
            
            
              '
            
            
              print
            
            (
            
              '
            
            
              resprint:
            
            
              '
            
            
              ,res)


test
            
            =
            
              myyield()

            
            
              print
            
            (next(test))
          

可以看到结果如下:

            C:\Users\11573\AppData\Local\Programs\Python\Python36\python.exe D:/pythonwork/socket/
            
              test.py
starting program
yes
            
          

有两行输出 但是我们发现并没有执行  

          print('resprint:'
          
            ,res)
          
        

这行代码,这是因为程序遇到yield关键字,然后把yield想像成return,return了一个yes之后,程序停止,并没有执行赋值给res操作,此时next(g)语句执行完成,所以输出的前两行

那么我们再修改下代码:

            
              def
            
            
               myyield():
    
            
            
              print
            
            (
            
              '
            
            
              starting program
            
            
              '
            
            
              )
    
            
            
              while
            
            
               True:
        res 
            
            = 
            
              yield
            
            
              '
            
            
              yes
            
            
              '
            
            
              print
            
            (
            
              '
            
            
              resprint:
            
            
              '
            
            
              ,res)


test
            
            =
            
              myyield()

            
            
              print
            
            
              (next(test))

            
            
              print
            
            (
            
              '
            
            
              //
            
            
              '
            
            *20
            
              )

            
            
              print
            
            (next(test))
          

可以看到输出如下:

            C:\Users\11573\AppData\Local\Programs\Python\Python36\python.exe D:/pythonwork/socket/
            
              test.py
starting program
yes

            
            ////////////////////////////////////////
            
              
resprint: None
yes
            
          

除了我们用作标记的 ‘////////////////////////////////////////‘ 外 多了两行输入

我们来看下这两行输出分别来自什么语句

首先输出resprint: None 这是因为上次程序中断在yield语句处 这次执行则直接从上次断点继续执行,而上次直接返回值,所以赋值为None 因此第一行输出resprint: None

第二行输出 yes 这是因为程序在while True循环中再次运行到了yield,因此又停止运行

因此通过这个简单的程序我们可以大概知道yield的用法了,带yield的函数是一个生成器,而不是一个函数了,这个生成器有一个函数就是next函数,next就相当于“下一步”生成哪个数,这一次的next开始的地方是接着上一次的next停止的地方继续执行。

send()

yield还有一个send()函数,那么send函数的作用是什么呢?我们可以举例子来看一下send()的作用

我们在上面代码的基础上增加几行代码:

            
              def
            
            
               myyield():
    
            
            
              print
            
            (
            
              '
            
            
              starting program
            
            
              '
            
            
              )
    
            
            
              while
            
            
               True:
        res 
            
            = 
            
              yield
            
            
              '
            
            
              yes
            
            
              '
            
            
              print
            
            (
            
              '
            
            
              resprint:
            
            
              '
            
            
              ,res)


test
            
            =
            
              myyield()

            
            
              print
            
            
              (next(test))

            
            
              print
            
            (
            
              '
            
            
              //
            
            
              '
            
            *20
            
              )

            
            
              print
            
            
              (next(test))

            
            
              print
            
            (
            
              '
            
            
              //
            
            
              '
            
            *20
            
              )

            
            
              print
            
            (test.send(
            
              '
            
            
              sending yes
            
            
              '
            
            ))
          

看下输出:

            C:\Users\11573\AppData\Local\Programs\Python\Python36\python.exe D:/pythonwork/socket/
            
              test.py
starting program
yes

            
            ////////////////////////////////////////
            
              
resprint: None
yes

            
            ////////////////////////////////////////
            
              
resprint: sending yes
yes
            
          

奇怪,之前的resprint都是None,这次却有了赋值,

这是因为,send是发送一个参数给res的,在next函数return的时候,并没有把 'yes' 赋值给res,下次执行的时候只好继续执行赋值操作,只好赋值为None了,而如果用send的话,开始执行的时候,先接着上

一次(return yes之后)执行,先把 'sending yes' 赋值给了res,然后执行next的作用,遇见下一回的yield,return出结果后结束。send方法中包含next()方法,所以程序会继续向下运行执行print方法,然后再次

进入while循环程序执行再次遇到yield关键字,yield会返回后面的值后,程序再次暂停,直到再次调用next方法或send方法。

 


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论