def f():
for x in xrange(0, 5):
y = yield x
print y
g = f()
g.send(None)
上面是一个简单的生成器,在第一次调用g.send(None)
的时候,生成器开始从头一直执行到yield处(yield未返回),生成器暂停,并携带生成器内部的x返回到外部调用生成器的地方,也就是g.send(None)
返回了,而且返回值就是yield携带出来的x,如果我们再在生成器外部调用g.send('hello')
,那么这个调用会携带参数'hello'再次进入到生成器暂停的地方,里面的yield表达式会返回,而返回值就是在外部send进去的参数'hello'.
从以上的过程可以看出,yield表达式可以即可以向生成器外部返回值,又可以接受外部传进来的值,最重要的是它可以在任意地方中断函数的执行又恢复回来,这些特性使得生成器像线程一样可以与其他线程交互,还可以被中断,被调度,但是不像线程那样会被随机地中断,生成器被中断的地方是被显示地规定了的,也就是yield出现的地方,而且这种中断仅发生在语句和语句之间,而不是像线程中断那样会发生在更小粒度的指令之间,这样就不需要像线程那样需要各种锁来同步,有了生成器我们就可以在自己的控制下切换逻辑流。
实际上python中生成器便是协程,只不过生成器一般只是从内部单向地向外发送数据,而协程更强调内部和外部的交互和调度。