在python中使用了 yield 关键字的函数并不是普通的函数,而是被称为生成器(generator)。生成器是一个返回迭代器的函数,只能用于迭代操作,更简单点理解生成器就是一个迭代器。
在调用生成器运行的过程中,每次遇到 yield 时函数会暂停并保存当前所有的运行信息,返回 yield 的值, 并在下一次执行 next() 方法时从当前位置继续运行。通过以下例子来理解:
def test():
i = 0
while(i < 5):
temp = yield i**2
print(temp)
i += 1
t = test()
print(next(t))
print(next(t))
#输出为
#0
#none
#1
之所以运行结果是这样,我们可以将两个print()分开来看(需要注意的是t = test()这步并没有执行test函数,而是在next()函数处才开始执行):
第一个print():
当执行next(t)函数时,test()开始执行,当进入到yield关键字处时程序被暂停,并将yield关键字后的数据返回出去,所以第一个print显示的就是0。并且程序将不会继续运行,直到第二个next(t)被调用。
第二个print():
程序开始从暂停处继续执行,因为当程序被暂停时,并没有开始赋值给temp的操作。而且yield后的数据又被返回出去了,所以并没有值可以赋给temp了,则print(temp)输出就为none。接着开始循环执行到第二次遇到yield关键字,继续返回后面的i**2,同时暂停程序,直到下一个next()。。。。。
send() 的用法
当只有一个print(next(t))时:
def test():
i = 0
while(i < 5):
temp = yield i**2
print(temp)
i += 1
t = test()
print(next(t))
#输出为
#0
输出该结果的原因是yield处程序被暂停,但是如果在后面加上一句
print(t.send("blank"))
def test():
i = 0
while(i < 5):
temp = yield i**2
print(temp)
i += 1
t = test()
print(next(t))
print(t.send("blank"))
则结果为
0
blank
1
所以send()相当于将send()中的参数赋给了函数中正缺少值的temp,并且使函数继续运行,直到遇到下一次的yield。
可以想象为人走在路上遇到一个坑就停下了,而send相当于把坑填上,而人也可以继续行走直到遇到下一个坑或者走到目的地。
def test():
i = 0
while(i < 5):
temp = yield i**2
print(temp)
i += 1
t = test()
print(next(t))
print(t.send("blank"))
print(t.send("blank"))
print(t.send("blank"))
print(t.send("blank"))
print(t.send("blank"))#程序结束,将报错
0
blank
1
blank
4
blank
9
blank
16
blank
Traceback (most recent call last):
File "pytest.py", line 13, in <module>
print(t.send("blank"))
StopIteration
而print(next(t))等同于send(None)