jield的本质是将函数变成一个生成器和迭代器
【例】
import types
from collections import Iterable
#from inspect import isgeneratorfunction
def helloYield(n):
print("HHHA:0====>")
for i in range(n):
print("HHHA:0.1====>")
n = yield i
print("HHHA:0.2====>", n)
print("HHHA:1====>")
print("HHHH:0========>")
yieldReval = helloYield(5)
print("HHHH:1========>")
print("yieldReval is GeneratorType ? : ", isinstance(yieldReval, types.GeneratorType))
print("yieldReval is Iterable ? : ", isinstance(yieldReval, Iterable))
#print("Iterable ? : ", isgeneratorfunction(yieldObj))
print("HHHH:2========>")
for i in yieldReval:
print("HHHB:0====>i=", i)
if i == 1:
print("HHHB:0.1====>send(99)")
yieldReval.send(99)
输出:
HHHH:0========>
HHHH:1========> //yieldObj = helloYield(5) //并未调用函数helloYield()
yieldReval is GeneratorType ? : True //返回值是一个生成器
yieldReval is Iterable ? : True //返回值是一个迭代器
HHHH:2========> //开始用for 来遍历生成器
HHHA:0====> //for 循环暂停,helloYield()函数开始执行,
HHHA:0.1====> //直到遇到“yield"时,helloYield()函数暂停,并将yield后面的值返回给for
HHHB:0====>i= 0 //for 恢复执行,直到本次循环结束或者yieldReval.send()时暂停
HHHA:0.2====> None //helloYield()函数恢复执行...
HHHA:0.1====> //直到再遇到yield ...
HHHB:0====>i= 1
HHHB:0.1====>send(99) //for向helloYield发送数值
HHHA:0.2====> 99 //helloYield()收到数值
HHHA:0.1====>
HHHA:0.2====> None //(重复上面的过程)...
HHHA:0.1====>
HHHB:0====>i= 3
HHHA:0.2====> None
HHHA:0.1====>
HHHB:0====>i= 4
HHHA:0.2====> None //直到helloYield()再也无法遇到yield,将抛出StopIteration异常
HHHA:1====> //for 循环遇到StopIteration异常时结果整个循环体
要点:
1.包含“yield”的函数不再是普通函数,而是一个生成器+迭代器+函数;
2.访问jieldReval时,原执行处的代码与helloYield()函数的代码“交叉执行”;
3.单线程!(两处代码“同时”执行,没有既没有线程切换也没有加锁——这是yield最特别的地方);
参考:https://www.liaoxuefeng.com/article/001373892916170b88313a39f294309970ad53fc6851243000