在阅读这篇文章以前,你应该已经了解python中的迭代器。如果不清楚的话,可以参考我的另一篇文章: 《Python高级编程之初识迭代器》
1. yield语句在之前的文章中,我们使用类来创建自己的迭代器,实现过程稍微麻烦一点:
class yrange: def __init__(self, start=0, stop=0): self.start = start self.stop = stop def __iter__(self): return self def next(self): if(self.start < self.stop): start = self.start self.start += 1 return start else: raise StopIteration生成器函数可以简化迭代器的创建。只要在函数中使用 yield 语句来替代结果的输出,就变成了一个生成器函数。
下面的代码实现了与上述的类等价的功能
def zrange(start=0, stop=0): while start < stop: yield start start += 1可以看到,实现的过程非常简洁。
2. 生成器生成器的工作方式与迭代器相同,可以被视为是迭代器的一种。需要注意的是,生成器只支持一遍的迭代。当一个生成器被迭代完之后,就无法再产生结果,此时必须使用一个新的生成器以便再次迭代。
如果我们调用上面示例中定义的生成器函数,将会得到一个生成器。
>>> zrange(0, 10) <generator object zrange at 0x03910BC0>我们可以像使用其它迭代器一样使用生成器。
>>> for z in zrange(5, 8): ... print z 5 6 7 3. 生成器函数工作原理生成器函数与普通函数最显著的不同就是它没有 return 语句,取而代之的是 yield 语句。
正常的函数在被调用后,会通过 return 语句返回一个值,然后结束。而生成器函数被调用后,返回的生成器类似于一个函数环境,每次迭代过程中执行到 yield 语句,就会返回一个值,然后挂起函数,等下一次迭代时再恢复函数的状态,继续执行其它语句,直到再次遇到 yield 语句时重复上述过程。
我们用一个例子来观察生成器函数的运行过程:
>>> def gen(stop): ... start = 0 ... print "Generator starts" ... while(start < stop): ... print "Before", start ... yield start ... print "After", start ... start += 1 ... print "Generator stops" >>> G = gen(3) >>> G.next() Generator starts Before 0 0 >>> G.next() After 0 Before 1 1 >>> G.next() After 1 Before 2 2 >>> G.next() After 2 Generator stops Traceback (most recent call last): File "<interactive input>", line 1, in <module> StopIteration可以看到,每次执行到 yield 语句,函数将被挂起,在下次迭代时函数恢复,继续执行。
在迭代到达末尾时,生成器触发了 StopIteration 异常,遵循迭代协议。单从生成器的工作方式来看,与迭代器是一样的。
4. 生成器表达式除了通过生成器函数来得到生成器之外,还可以使用生成器表达式来实现。
生成器表达式与列表推导式的语法一致,不同之处在于生成器表达式使用一对圆括号来包围表达式,而列表推导式使用的是方括号。
生成器表达式的基本用法如下:
>>> L = [1, 2, 3] >>> G = (x ** 2 for x in L)变量 G 就是我们得到的生成器,下面对它进行迭代
>>> for i in G: ... print i 1 4 9这里只提到了生成器表达式最简单的语法,如果要更深入了解生成器表达式,可以参考具有相同语法的列表推导式,只要把表达式的方括号替换为圆括号即可。
相关文章: 《Python高级编程之列表推导式》