最近又把python的generator重新看了一下,主要参考了。
yield_atom ::= "(" yield_expression ")"
yield_expression ::= "yield" [expression_list]
expression_list ::= expression ( "," expression )* [","]
如果在一个函数里面用到了yield表达式,那么这个函数就是一个generator函数。
当一个generator函数被调用,他会返回一个迭代器,这个迭代器就是generator。然后这个generator就控制了这个generator函数的执行。
当某个generator的函数被调用的时候,这个generator函数开始执行,当执行到第一个generator表达式的时候,这个函数挂起,然后返回expression_list的值.
当再次调用generator的某个函数的时候,generator函数继续执行。
generator函数再次开始执行时的yield表达式的值依赖于所调用的generator函数。
generator.next()
开始执行一个generator函数或者从上次执行yield表达式的地方从新开始执行generator函数。当generator函数通过next()函数继续执行时,当前的yield表达式总得值总是None。此时,这个generator函数继续执行到下一个yield表达式的地方,然后挂起,同时将yield表达式的值返回。如果generator函数后面如果没有yield表达式了,就抛出一个StopIteratio。
generator.send(value)
继续执行一个generator函数。value这个参数变成了当前的yield表达式的值。send返回下一个yield产生的值,如果后面没有yield了,会抛出StopIteration异常。当调用send()来启动generator的时候,value这个参数必须是None,因为这个时候没有yield表达式来接受参数。
generator.throw(type[, value[, traceback]])
在generator挂起的地方抛出一个type类型的异常type,返回下一个yield产生的值。如果这个generator没有产生其他的值就退出了,会抛出一个StopIteration异常。如果generator函数没有捕捉到传进来的异常或者抛出了其他的异常,这个异常会被返回回去。
generator.close()
在generator函数挂起的地方抛出一个GeneratorExit异常。如果这个generator函数继续抛出StopIteration异常(因为正常退出或者已经被close了),或者抛出GeneratorExit异常(因为没有能够捕获这个异常),close()将把这个异常返回。如果这个generator产生了一个值,一个RuntimeError将会被抛出。如果generator抛出任何异常,都会被返回。如果这个generator因为一个异常或者正常退出而已经推出了,close()将什么也不做。
close就相当于普通的close方法,当调用了close之后,如果在调用next或者send就会抛出一个异常。
下面是对python文档中的例子的实践,以及根据自己的理解的一些解释。
代码如下:
#coding:utf-8
def echo(value=None):
print "Execution starts when 'next()' is called for the time."
try:
while True:
try:
print type(value)
value = (yield value)
print type(value)
except Exception, e:
value = e
finally:
print "Don't forget to clean up when 'close()' is called."
if __name__ == "__main__":
generator = echo(1)
print generator.next() #输出:Execution starts when 'next()' is called for the time.
#执行到了value = (yield 1)
#返回1,挂起。value = (yield 1)没有执行完,此时左值的value仍然是None
print "="*3
print generator.next() #接着value = (yield 1)开始执行。左值value这时是None
#执行到value = (yield None)
#返回None
print "="*3
print generator.send(2) #先执行value = (yield None)。因为是send(2),所以此时左值value的值为2
#然后继续执行循环value = (yield 2)。
#因为send()返回下一个yield表达式中的表达式(expression_list)的值,所以此时返回2,挂起。此时左值value的值为None。
print "="*3
generator.throw(TypeError, "spam") #先执行value = (yield 2)
#然后抛出异常,这个异常被"except Exception, e:"捕捉,并处理,这时value是TypeError
#然后继续循环到value = (yield TypeError),返回yield表达式,也就是TypeError这个异常。然后挂起。
print "="*3
print generator.close() #继续执行value = (yield TypeError),抛出GeneratorExit异常。
#这个异常被"except Exception, e:"捕获,并处理,这时value为GeneratorExit。
#继续执行循环,执行到value = (yield GeneratorExit),返回GeneratorExit。
#这相当于generator产生了一个值,所以就会抛出一个RuntimeError异常。
|
运行结果如下:
C:\>python test.py
Execution starts when 'next()' is called for the time.
1
===
None
===
2
===
===
Traceback (most recent call last):
File "test.py", line 38, in
print generator.close() #继续执行value = (yield TypeError),抛出GeneratorExit异常。
RuntimeError: generator ignored GeneratorExit
Exception exceptions.RuntimeError: 'generator ignored GeneratorExit' in ignored
阅读(2876) | 评论(0) | 转发(0) |