生成器的定义
带有yield语句的方法、函数,就是一个生成器。yield语句返回的实际上是一个生成器(generator对象)。生成器也是一种特殊的迭代器,与迭代器不同的是,它可以保存程序执行的contex,这样就可以再次返回到方法、函数中运行。
示例:
def fib():
"""生成器实现斐波那契额数列"""
a, b = 0, 1
while True:
yield b
a, b = b, a+b
运行结果:
上面定义了一个函数fib,然后通过next重复调用fib函数对象f,就可以生成斐波那契额数列。
函数每次直行道yiled时,会返回给调用对象b的值(fib函数的运行“现场”会保存),fib函数暂停执行,再次通过next调用时,fib会继续执行,再次执行到yield时再次返回,fib函数暂停……这个过程可以一直重复直至程序终止。
上结果中,最后一行代码next(fib())返回的是1,而不是5,是因为fib()函数重新生成了一个生成器,而不是f,所以fib函数重新开始运行。如果继续调用next(f),输出应该是5。
send实现代码交互
上面的例子中,调用fib对象f时,只能从fib函数中返回一个值,能不能给fib函数传递一个值呢?但是可以的,可以通过send来实现。
示例:
def AnswerRobot():
print("欢迎光临")
while True:
problem = (yield)
if problem is not None:
if problem.endswith('?'):
print("不用问太多问题啦")
elif 'Good morning' in problem:
print("Good morning.")
elif 'Good night' in problem:
print("It's too early to sleep.")
运行结果:
基于上面的运行结果,可以理解yield和send的用法。yield是从函数中返回(本例返回空),而send是从调用程序中给函数传递一个值,函数执行过程中遇到yiled就按下了暂停键,每次调用next时,函数继续执行,遇到yiled时返回,调用send时,传递一个值给yield返回处,同时再次运行。这样就可以实现调用代码和生成器对象的交互执行。