协程
yield
yield是实现生成器的关键。一个函数中使用了yield,这个函数就被称为生成器。
def demo(n):
for i in range(n):
yield i
d = demo(n) # generator
调用这个函数不会执行,而是返回一个iterable对象,然后通过以下几个重要的方法去处理这个对象。
next(generator)
当调用next()方法时,程序开始执行。当走到yield时停下,将yield之后的值返回。当下一个next()方法到来时,程序接着从上一次等待的地方继续运行。
定义一个简单的生成器
def demo(n):
for i in range(n):
yield i
调用next()方法
>>> d = demo(5)
>>> next(d)
0
>>> next(d)
1
>>> next(d)
2
......
可以看到next()的返回值就是yield后跟的变量。如果yield后不跟任何变量,则返回None。
generator.send(value)
send(value)方法将value传递给yield表达式的返回值,并且将该值返回。
将上面的生成器修改一下
def demo(n):
for i in range(n):
temp = yield i
print(temp)
调用send()方法
>>> d = demo(5)
>>> next(d)
0
>>> next(d)
None
1
>>> d.send(100)
100
2
>>> next(d)
None
3
......
我们将yield i表达式赋值给了temp变量,当调用send()方法时,传递的值赋值给了temp。
也即是说:next()的返回值是yield后的值,send()的返回值是它本身传递的参数值,并且该值还会赋值给yield语句的结果
generator.throw(Error)
在生成器中抛出异常,返回下一个yield的值或者StopIteration。
依旧使用上面的例子
>>> d = demo(5)
>>> next(d)
0
>>> next(d)
None
1
>>> d.throw(StopIteration)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "\path\to\demo.py", line 3, in demo
temp = yield i
StopIteration
>>> next(d)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
......
当调用throw()后,触发异常,迭代中断,后续的next()都只会得到一个StopIteration异常
能触发StopIteration异常的操作有:
- 迭代终止时。包括捕获异常,迭代完成。再次调用
next()时将抛出异常 - 手动调用
close()关闭生成器函数 - 执行过程中遇到
return关键字,将直接抛出异常,如果return某一具体的值,该值为异常的说明 ```python def demo(n): for i in range(n): yield i return ‘description for StopIteration’
d = demo(2) print(next(d))
0
print(next(d))
Traceback (most recent call last):
File “", line 1, in
StopIteration: desc
```