Python 中的协程 yield from

Posted wang-kai-1994

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python 中的协程 yield from相关的知识,希望对你有一定的参考价值。

1 yiled from 的定义

  从字面看是yield的升级改进版本,如果将 yield 理解成返回,那么 yield from 就是从哪里返回。

def generator2():
    yield a
    yield b
    yield c
    yield from [11,22,33,44]
    yield from (12,23,34)
    yield from range(3)

for i in generator2():
    print(i,end= , )
# a , b , c , 11 , 22 , 33 , 44 , 12 , 23 , 34 , 0 , 1 , 2 , 

yield from 返回另一个生成器。而yield 只返回一个元素。有下面的等价关系:

yield from iterable == for item in iterable: yield item。

 

2 yield from 的高级应用

  使用for 循环迭代生成器时,不会显式的触发StopIteration异常,因为 for 循环的底层处理了这个异常,因此也就不会得到return 的返回值。

  

def my_generator():
    for i in range(5):
        if i==2:
            return 我被迫中断了
        else:
            yield i

def main(generator):
    try:
        for i in generator:  #不会显式触发异常,故而无法获取到return的值
            print(i)
    except StopIteration as exc:
        print(exc.value)

g=my_generator()  #调用
main(g)

# 0  1

如果使用 next 来迭代会显示的触发异常,虽然能够获取return 的返回值,但是操作麻烦。

而使用 yield from 来实现这个需求:

def my_generator():         # 子生成器
    for i in range(5):
        if i==2:
            return 我被迫中断了
        else:
            yield i

def wrap_my_generator(generator):  # 委托生成器
    result=yield from generator
    #自动触发StopIteration异常,并且将return的返回值赋值给yield from表达式的结果,即result
    print(这是return 的返回值,,result)

def main(generator):        # 调用方
    for j in generator:
        print(j)

g=my_generator()
wrap_g=wrap_my_generator(g)
main(wrap_g)  #调用
‘‘‘运行结果为:
0
1
这是return 的返回值, 我被迫中断了
‘‘‘
yield from 的特点:
  1. 上面的my_generator是原始的生成器即子生成器,main是调用方,wrap_my_generator是委托生成器

  2. 在使用yield from的时候,多了一个 委托生成器,调用方通过委托生成器来与子生成器进行交互。

  3. 委托生成器会为调用方和子生成器建立双向通道,即调用方可以和子生成器直接进行交互,委托生成器不参与代码的处理,只负责充当管道的作用以及接收 return 的返回值。

  4. yield from iteration结构会在内部自动捕获 iteration生成器的StopIteration 异常,把return返回的值或者是StopIteration的value 属性的值变成 yield from 表达式的值。

yield from主要设计用来向子生成器委派操作任务,但yield from可以向任意的可迭代对象委派操作。

委派生成器(group)相当于管道。可以把任意数量的委派生成器线形连接在一起。

以上是关于Python 中的协程 yield from的主要内容,如果未能解决你的问题,请参考以下文章

理解Python协程:从yield/send到yield from再到async/await

理解Python协程:从yield/send到yield from再到async/await

关于Python的协程问题总结

Python异步IO之协程:从yield from到async的使用

Python并发编程理解yield from协程

协程由两个带 while循环的函数和yield组建的协程