参考:http://aju.space/2017/07/31/Drive-into-python-asyncio-programming-part-1.html
yield from
是Python 3.3 新引入的语法(PEP 380)。
它主要解决的就是在生成器里玩生成器不方便的问题。它有两大主要功能;
第一个功能是:让嵌套生成器不必通过循环迭代yield
,而是直接yield from
。
以下两种在生成器里玩子生成器的方式是等价的:
# 方式一:使用 yield def gen_two(): subgen = (i**2 for i in range(2,5)) for item in subgen: yield item b = gen_two() print(type(b),b) for j in b: print(j) # 方式二:使用 yield from def gen_one(): subgen = (i**2 for i in range(2,5)) yield from subgen a = gen_one() print(type(a),a) for i in a: print(i)
第二个功能:在子生成器和原生成器的调用者之间打开双向通道,两者可以直接通信。
def gen(): yield from subgen() print("end gen...") def subgen(): try: while True: x = yield yield x+1 except Exception as e: print("StopIteration in subgen...") if __name__ == '__main__': g = gen() g.send(None) # 驱动生成器g开始执行到第一个 yield retval = g.send(1) # 看似向生成器 gen() 发送数据 print(retval) # 返回2 g.throw(StopIteration) # 看似向gen()抛入异常 ### 结果 ### 2 StopIteration in subgen... end gen... Traceback (most recent call last): File "D:/soft/work/Python_17/day25/async_IO/xxx.py", line 75, in <module> g.throw(StopIteration) # 看似向gen()抛入异常 StopIteration
关键字yield from在gen()内部为subgen()和main()开辟了通信通道。 main()里可以直接将数据1发送给subgen(), subgen()也可以将计算后的数据2返回到main()里; main()里也可以直接向subgen()抛入异常以终止subgen()。 顺带一提: yield from 除了可以 yield from <generator> 还可以 yield from <iterable>。