Chinaunix首页 | 论坛 | 博客
  • 博客访问: 469427
  • 博文数量: 111
  • 博客积分: 2332
  • 博客等级: 大尉
  • 技术积分: 1187
  • 用 户 组: 普通用户
  • 注册时间: 2009-08-29 11:22
文章分类

全部博文(111)

文章存档

2013年(9)

2012年(28)

2011年(17)

2010年(28)

2009年(29)

我的朋友

分类: Python/Ruby

2010-03-21 15:46:01

最近又把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
阅读(2793) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~