Python 函数的定义体中有 yield 关键字, 该函数就是生成器函数。 调用生成器函数时, 会返回一个生成器对象。生成器函数的定义体执行完毕后, 生成器对象会抛出StopIteration 异常。
def gen_A():
print('start')
yield 1
print('starting')
yield 2
print('starting')
yield 3
print('end')
>>> it = iter(gen_A())
>>> next(it)
start
1
>>> next(it)
starting
2
>>> next(it)
starting
3
>>> next(it)
end
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
>>>
>>> for i in gen_A():
... print(i)
...
start
1
starting
2
starting
3
end
这里清楚地显示了生成器的执行过程
for循环第一次调用next(),打印出start,生成器函数定义体中的yield语句,返回生成值1
for循环第二次调用next(),由yield 1 前进到 yield 2 打印出starting,生成器函数定义体中的yield语句,返回生成值2
for循环第三次调用next(),由yield 2 前进到 yield 3 打印出starting,生成器函数定义体中的yield语句,返回生成值3
for循环第四次调用next(),打印出end,到达函数定义体的末尾, 导致生成器对象抛出 StopIteration 异常。for机制捕获异常, 因此循环终止时没有报错。
生成器函数会创建一个生成器对象, 包装生成器函数的定义体。 把生成器传给 next(...) 函数时, 生成器函数会向前, 执行函数定义体中的下一个 yield 语句, 返回产出的值, 并在函数定义体的当前位置暂停。 最终, 函数的定义体返回时, 外层的生成器对象会抛出StopIteration 异常——这一点与迭代器协议一致