协程的四个状态
使用inspect.getgeneratirstat()
获取协程的状态
等待开始执行
GEN_CREATED
解释器正在执行
GEN_RUNNING
在yield表达式处暂停
GEN_SUPENDED
执行结束
GEN_CLOSED
使用协程计算平均值
def averager():
total = 0.0
count = 0
average = None
while True:
term = yield average
total += term
count += 1
average = total / count
if __name__ == '__main__':
c = averager()
next(c) # 预激
print(c.send(10))
print(c.send(20))
print(c.send(30))
print(c.send(5))
协程的终止与异常处理
class DemoException(Exception):
pass
def demo():
print('协程开始')
try:
while True:
try:
x = yield
except DemoException:
print('已知异常DemoException')
else:
print(f"输入了:{x}")
finally:
print('协程结束')
if __name__ == '__main__':
d = demo()
next(d)
d.send(10)
d.send(11)
d.throw(DemoException)
print('1234')
d.close()
yield from
Yield from 的主要功能是打开双向通道,把最外层的调用方与最内层的子生成器连接起来,这样两者可以直接发送和产出值,还可以直接传出异常,而不用在位于中间的协程中添加大量处理异常的样板代码。
委派生成器
包含yield from <iterable>
表达式的生成器函数
子生成器
从yield from
表达式中<iterable>
部分获取的生成器
调用方
指代委派生成器的客户端代码
例子
from collections import namedtuple
Result = namedtuple('Result', 'count average')
# 子生成器
def averager():
total = 0.0
count = 0
average = None
while True:
term = yield
if term is None:
break
total += term
count += 1
average = total / count
return Result(count, average)
# 委派生成器
def grouper(results, key):
while True:
results[key] = yield from averager()
# 客户端代码,调用方
def main(data):
results = {}
for key, values in data.items():
group = grouper(results, key)
next(group)
for value in values:
group.send(value)
group.send(None)
report(results)
# 输出报告
def report(results):
for key, result in sorted(results.items()):
group, unit = key.split(';')
print(f'{result.count:2} {group:5} averaging {result.average:.2f}{unit}')
data = {
'girls;kg': [40.9, 38.5],
'girls;m': [1.6, 1.51],
'boys;kg': [39.9, 38.5],
'boys;m': [1.5, 1.46],
}
if __name__ == '__main__':
main(data)
输出:
2 boys averaging 39.20kg
2 boys averaging 1.48m
2 girls averaging 39.70kg
2 girls averaging 1.56m