Python 中的协程 (2) 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)相当于管道。可以把任意数量的委派生成器线形连接在一起。

原文地址:https://www.cnblogs.com/wang-kai-1994/p/10375202.html