当定义的方法和函数中有 yield 关键字,这个执行这个函数或者方法就将返回一个生成器对象,这个生成器对象可以被for循环迭代,也可以手动执行next或者send方法精准控制这个生成器的内部执行,我们看如下代码就可以简单理解 yield,next和send之间的关系和用法:
#!/usr/bin/env python
import types
def gen():
print 'enter'
a = yield 1 #StateA
print 'next'
print a or 'a'
b = yield 2 #StateB
print b or 'b'
print 'next again'
g = gen()
print(type(g))
print('g isinstance types.GeneratorTyp : '+ str(isinstance(g, types.GeneratorType)))
print(g.next())
i=0
while(i>=0):
i += 1
print 'i:'+str(i)
try:
print(g.send('x'))
except StopIteration:
break
print('--------------')
g2 = gen()
print(type(g2))
for x in g2:
print(x)
执行上述代码将打印如下信息:
<type 'generator'>
g isinstance types.GeneratorTyp : True
enter
i:1
next
x
i:2
x
next again
--------------
<type 'generator'>
enter
next
a
b
next again
详细解释一下执行过程
1、定义生成器函数
def gen()
2、获得迭代器对象,并赋值给g,同时我们打印g的类型,返回generator,可以看到我们类型判断为 generator
g = gen()
3、执行迭代器到到第一个yield处,此处打印1,然后迭代器就挂起了,等待下一次调用,我们暂时命名此出挂起状态为StateA。
print(g.next())
4、进入while循环,第一次执行循环,打印“i:1”,然后执行如下代码
print(g.send('x'))
上述代码将继续 StateA 状态开始执行,首先将字符串“x”发送到迭代器中,然后迭代器开始运行,将字符串“x”复制给变量a,然后打印出:
print 'next' #next
print a or 'a' #x
接着运行到下一个 yield,返回yield值“2”到send函数,于是在while循环中就打印出了“2”,这时迭代器函数的状态运行到StateB
5、再次进入while循环,send函数将字符串“x”传递进迭代器,赋值给b,这样迭代器就打印出
print b or 'b' #x
print 'next again' #next again
然后由于迭代器中没有 yield 操作,将抛出一个 StopIteration 异常,我们接受到 StopIteration 异常就终止循环。
6、通过使用for循环来迭代一个迭代器对象更简单,不需要判断 StopIteration 异常就可以获取yield传出来的值,直接将其打印出