前言
本文将由浅入深详细介绍yield以及generator,包括以下内容:什么generator,生成generator的方法,generator的特点,generator基础及高级应用场景,generator使用中的注意事项。本文不包括enhanced generator即pep342相关内容,这部分内容在之后介绍。
generator基础
在python的函数(function)定义中,只要出现了yield表达式(Yield expression),那么事实上定义的是一个generator function, 调用这个generator function
返回值是一个generator。这根普通的函数调用有所区别,For example:
def gen_generator(): yield 1def gen_value(): return 1 if __name__ == '__main__': ret = gen_generator() print ret, type(ret) #<generator object gen_generator at 0x02645648> <type 'generator'> ret = gen_value() print ret, type(ret) # 1 <type 'int'>
从上面的代码可以看出,gen_generator
函数返回的是一个generator实例
generator有以下特别:
•遵循迭代器(iterator)协议,迭代器协议需要实现__iter__
、next接口
•能过多次进入、多次返回,能够暂停函数体中代码的执行
下面看一下测试代码:
>>> def gen_example():... print 'before any yield'... yield 'first yield'... print 'between yields'... yield 'second yield'... print 'no yield anymore'... >>> gen = gen_example()>>> gen.next() # 第一次调用nextbefore any yield'first yield'>>> gen.next() # 第二次调用nextbetween yields'second yield'>>> gen.next() # 第三次调用nextno yield anymoreTraceback (most recent call last): File "<stdin>", line 1, in <module>StopIteratio
调用gen example方法并没有输出任何内容,说明函数体的代码尚未开始执行。当调用generator的next方法,generator会执行到yield 表达式处,返回yield表达式的内容,然后暂停(挂起)在这个地方,所以第一次调用next打印第一句并返回“first yield”。 暂停意味着方法的局部变量,指针信息,运行环境都保存起来,直到下一次调用next方法恢复。第二次调用next之后就暂停在最后一个yield,再次调用next()
方法,则会抛出StopIteration异常。
因为for语句能自动捕获StopIteration异常,所以generator(本质上是任何iterator)较为常用的方法是在循环中使用:
def generator_example(): yield 1 yield 2if __name__ == '__main__': for e in generator_example(): print e # output 1 2
generator function产生的generator与普通的function有什么区别呢
(1)function每次都是从第一行开始运行,而generator从上一次yield开始的地方运行
新闻热点
疑难解答