yield是在定义生成器时使用,只能在函数体内使用,使得该函数变成一个生成器函数而不是普通的函数,然后该函数在调用时会返回生成器。
生成器像是个协程,多次yield,有多个进入点,执行会被暂停。但是生成器函数只要在调用了yield之后就不能再控制是否可继续执行,控制权就交给调用者了。
用于控制生成器的函数
generator.next()
启动执行一个生成器或恢复执行它
当生成器恢复的时候,当前的yield产生的值就变成空了,生成器继续执行,再yield一个值,则这个值就被返回给调用者了,不yield同时生成器结束执行则抛出[StopIteration]
generator.send(value)
恢复执行并把value发送到生成器函数中
value值就变成当前的yield产生的值,生成器继续执行,再yield一个值,则这个值就被返回给调用者了,不yield同时生成器结束执行则抛出[StopIteration],如果是使用send方式来启动一个生成器则参数虚伪None,因为没有所谓的当前yield产生的值来接收它。
generator.throw(type[, value[, traceback]])
在生成器当前暂停的地方抛出异常,type为异常的种类,并把下一个生成器产生的值yield出,如果生成器退出了并没有yield值,那么会抛出StopIteration,如果生成器中没有捕获异常或抛出了不同的异常,那么该异常会衍生到调用者。
generator.close()
在生成器当前暂停的地方产生 [GeneratorExit]异常。
如果生成器抛出[StopIteration](正常结束或已经被关闭时)或者[GeneratorExit](生成器中没有捕获异常的操作所以直接衍生给调用者),则控制权返回给调用者,如果此时生成器yield一个值会造成[RuntimeError],如果抛出的是其他异常,也会衍生到调用者。如果生成器已经结束了则不会造成任何影响。
If the generator function does not catch the passed-in exception, or raises a different exception, then that exception propagates to the caller.
>>> def echo(value=None):
... print "Execution starts when 'next()' is called for the first time."
... try:
... while True:
... try:
... value = (yield value)
... except Exception, e:
... value = e
... finally:
... print "Don't forget to clean up when 'close()' is called."
...
>>> generator = echo(1)
>>> print generator.next()
Execution starts when 'next()' is called for the first time.
1
>>> print generator.next()
None
>>> print generator.send(2)
2
>>> generator.throw(TypeError, "spam")
TypeError('spam',)
>>> generator.close()
Don't forget to clean up when 'close()' is called.
优势
线程极高的执行效率,没有线程切换开销,不加锁,通过多进程+协程利用多核CPU。