【Python那些事儿之八】Generators详解
by Harrison Feng in Python
生成器(Generator)在计算机科学中是用于控制循环迭代行为的一种特殊程序。简单的讲,它其实就是一个特别的
函数。在Python里,生成器是一个返回迭代器的函数。它与普通函数的区别就在于它包含一个yield语句。而yield语
句本身也只用于定义生成器。yield语句生成的是一个序列(一系列值)。这些值可以通过生成器对象的next()方法一
个一个返回。直到所有的值都返回完后,StopIteration的异常会被抛出。请看下面的代码:
-
def count_down(i):
-
print "Let's count down from %d" % i
-
while i > 0:
-
yield i
- i -= 1
-
>>> dcnt = count_down(5) # 调用生成器。
>>> dcnt
# 生成器对象。
>>> dcnt.next()
Let's count down from 5
5
>>> dcnt.next()
4
>>> dcnt.next()
3
>>> dcnt.next()
2
>>> dcnt.next()
1
>>> dcnt.next() # 所有的值都生成完后,StopIteration异常抛出。
Traceback (most recent call last):
File "", line 1, in
StopIteration
>>>
才会开始运行。而且next()返回的都是下一个值,直到所有的值都被返回完毕。其实yield语句在生成一个值后
(next()方法被调用时),它会暂停生成器函数,并记住当前的状态。当再次调用next()方法时,生成器函数被
恢复,继续生成下一个值,以此类推。上面的这个实验很好的展示了生成器的这一特性。
生成器函数提供了一种更便利的方式来创建迭代器(Iterator),而且不用关心迭代协议。生成器是一次性操作,
只能在生成器对象上完整遍历一次。如果还需要遍历,则需要重新调用生成器函数。
-
>>> dcnt = count_down(3)
>>> for i in dcnt:
... print i
...
Let's count down from 3
3
2
1
>>> for i in dcnt:
... print i
...
>>> -
>>> dcnt = count_down(3)
>>> for i in dcnt:
... print i
...
Let's count down from 3
3
2
1
>>>
在Python里,还有一种特殊的表达式,生成器表达式(Generator Expression)。一般情况下,如果一个
表达式返回的是一个迭代器(iterator),它就是生成器表达式(Generator Expression)。
最简单的生成器表达式:
-
>>> gx = (x ** 2 for x in xrange(10))
-
>>> gx
-
<generator object <genexpr> at 0x7f0cf1f254b0>
- >>>
生成器表达式的通用语法:
- (expression for i in s1 if cond1
- for j in s2 if cond2
- ...
- if condfinal)
-
for i in s1:
-
if cond1:
-
for j in s2:
-
if cond2:
-
...
- if condfinal: yield expression
最后,我们可以总结一下生成器的特性:
1)必须包含yield语句的函数。
2)在调用时不会运行。
3)调用生成器时生成的生成器对象只能被使用一次(遍历)。
4)返回迭代器,但是不用关心迭代协议。
by Harrison Feng in Python