python yield

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:Users11573AppDataLocalProgramsPythonPython36python.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:Users11573AppDataLocalProgramsPythonPython36python.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:Users11573AppDataLocalProgramsPythonPython36python.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:Users11573AppDataLocalProgramsPythonPython36python.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方法。

原文地址:https://www.cnblogs.com/CYHISTW/p/11153834.html