创建生成器(generator)有两种方法:
- 将list comprehension中的方括号[]变成圆括号()
>>> a=(i for i in range(10))
>>> a
<generator object <genexpr> at 0x02C0A9B8>
- 在函数中使用yield,该函数自动变成一个生成器
>>> def gen():
print 'generator'
yield 0
print 'step1'
yield 1
print 'step2'
yield 2
print 'Bye!'
>>> g=gen()
>>> g
<generator object gen at 0x02C0A788>
生成器的工作原理是,在执行生成器的时候(其实就是执行函数内的代码),遇到yield就立马停止,并返回yield后面的数据,直到yield下一行没有代码,此时抛出“StopIteration”异常,生成器停止工作。以上面定义的gen()为例进行说明。
>>> g=gen() # 得到生成器g
>>> g
<generator object gen at 0x02C0A788>
>>> g.next() # 执行生成器直到遇到yield
generator
0
>>> g.next() # 从上次执行yield命令的下一行继续执行,直到遇到下一个yield
step1
1
>>> g.next()
step2
2
>>> g.next() # yield后面没有内容,抛出'StopIteration'异常
Bye!
Traceback (most recent call last):
File "<pyshell#145>", line 1, in <module>
g.next()
StopIteration
如果将生成器放到for...in...中——for value in generator,则无需人工调用next()方法,当generator(函数执行过程中)遇到yield的时候,会将yield后面的数据返回给for中的value,然后程序会自动执行next()。如果遇到下一个yield,则重复前面的过程;如果程序执行完毕,则退出for循环。
>>> g=gen()
>>> g
<generator object gen at 0x02C0A788>
>>> for i in g: # 每次将yield后面的数据返回给i
print '<value^2={}>'.format(i*i)
generator
<value^2=0>
step1
<value^2=1>
step2
<value^2=4>
Bye!
举例,下面的例子展示了输出长度为9的链表,链表中的内容是[0],[0,1],[0,1,2],...[0,1,2,...,8]。使用生成器可以不用将所有待打印的数据保存下来,每次执行过程中才生成相应的序列,然后打出输出。节省了内存空间。
>>> def gen(n):
a=range(n)
for i in a:
yield i
>>> l=[]
>>> for i in range(1,10):
l.append(gen(i))
>>> l
[<generator object gen at 0x02C4D2D8>, <generator object gen at 0x02C4E440>, <generator object gen at 0x02C4E148>, <generator object gen at 0x02C4E7D8>, <generator object gen at 0x02C4E670>, <generator object gen at 0x02C4EA80>, <generator object gen at 0x02C4E9E0>, <generator object gen at 0x02C4EC60>, <generator object gen at 0x02C4ED00>]
>>> for i in l:
for j in i:
print '[{}]value={}'.format(i,j)
[<generator object gen at 0x02C4D2D8>]value=0
[<generator object gen at 0x02C4E440>]value=0
[<generator object gen at 0x02C4E440>]value=1
[<generator object gen at 0x02C4E148>]value=0
[<generator object gen at 0x02C4E148>]value=1
[<generator object gen at 0x02C4E148>]value=2
[<generator object gen at 0x02C4E7D8>]value=0
[<generator object gen at 0x02C4E7D8>]value=1
[<generator object gen at 0x02C4E7D8>]value=2
[<generator object gen at 0x02C4E7D8>]value=3
[<generator object gen at 0x02C4E670>]value=0
[<generator object gen at 0x02C4E670>]value=1
[<generator object gen at 0x02C4E670>]value=2
[<generator object gen at 0x02C4E670>]value=3
[<generator object gen at 0x02C4E670>]value=4
[<generator object gen at 0x02C4EA80>]value=0
[<generator object gen at 0x02C4EA80>]value=1
[<generator object gen at 0x02C4EA80>]value=2
[<generator object gen at 0x02C4EA80>]value=3
[<generator object gen at 0x02C4EA80>]value=4
[<generator object gen at 0x02C4EA80>]value=5
[<generator object gen at 0x02C4E9E0>]value=0
[<generator object gen at 0x02C4E9E0>]value=1
[<generator object gen at 0x02C4E9E0>]value=2
[<generator object gen at 0x02C4E9E0>]value=3
[<generator object gen at 0x02C4E9E0>]value=4
[<generator object gen at 0x02C4E9E0>]value=5
[<generator object gen at 0x02C4E9E0>]value=6
[<generator object gen at 0x02C4EC60>]value=0
[<generator object gen at 0x02C4EC60>]value=1
[<generator object gen at 0x02C4EC60>]value=2
[<generator object gen at 0x02C4EC60>]value=3
[<generator object gen at 0x02C4EC60>]value=4
[<generator object gen at 0x02C4EC60>]value=5
[<generator object gen at 0x02C4EC60>]value=6
[<generator object gen at 0x02C4EC60>]value=7
[<generator object gen at 0x02C4ED00>]value=0
[<generator object gen at 0x02C4ED00>]value=1
[<generator object gen at 0x02C4ED00>]value=2
[<generator object gen at 0x02C4ED00>]value=3
[<generator object gen at 0x02C4ED00>]value=4
[<generator object gen at 0x02C4ED00>]value=5
[<generator object gen at 0x02C4ED00>]value=6
[<generator object gen at 0x02C4ED00>]value=7
[<generator object gen at 0x02C4ED00>]value=8
总结如下:
- 得到生成器的时候,并不会执行函数,只有当第一次调用next()方法的时候才会从函数的第一行开始执行
- 在函数内执行代码的过程中,一旦遇到yield关键字就会立马停止运行,并返回yield后面的内容。下次再调用next()方法会激活生成器,并从yield代码的下面一行开始继续执行。如果后面还会遇到yield,重复前面描述的过程。直到函数中的代码被执行完毕,此时会抛出‘StopIteration’异常