def gen():
    """子生成器"""
    yield  1

def gen1(gen):
    """委托生成器"""
    yield  from  gen

def main():
    """调用方"""
    g = gen()
    g1 = gen1(g)
    g1.send(None)  # 启动生成器

 

上面的代码有3个角色, main是调用方. gen1:委托生成器, gen:子生成器

yield from会在调用方与子生成器之间建立一个双方通道, 这样,调用方和子生成器之间就可以进行通信(send, close , throw )

 

示例

final_result = {}


def sales_num(key):
    total = 0
    nums = []
    while True:
        x = yield  # 使用while循环不断的从调用方接收值
        print(key + '销量:', x)
        if not x:
            break  # 结束while循环
        total += x
        nums.append(x)
    return total, nums # 生成器的值返回到delegate委托生成器中


def delegate(key):
    """委托生成器"""
    while True:
        final_result[key] = yield from  sales_num(key)
        print(key + '销量统计完成')


def main():
    data_set = {

        "欧莱雅": [100, 200, 400],
        "法泉": [12, 4354, 67],
        "死贵人": [212, 23423, 545]
    }

    for key, data in data_set.items():
        print('start key:', key)
        d = delegate(key)
        d.send(None)
        for value in data:
            d.send(value)  # 这儿是直接将值send到sales_num子生成器中
        d.send(None) # 结果一个key的统计
    print('final_result:', final_result)


if __name__ == '__main__':
    main()

 

打印:

start key: 欧莱雅
欧莱雅销量: 100
欧莱雅销量: 200
欧莱雅销量: 400
欧莱雅销量: None
欧莱雅销量统计完成
start key: 法泉
法泉销量: 12
法泉销量: 4354
法泉销量: 67
法泉销量: None
法泉销量统计完成
start key: 死贵人
死贵人销量: 212
死贵人销量: 23423
死贵人销量: 545
死贵人销量: None
死贵人销量统计完成
final_result: {'欧莱雅': (700, [100, 200, 400]), '法泉': (4433, [12, 4354, 67]), '死贵人': (24180, [212, 23423, 545])}

 

 

补充

 

def sales_num(key):
    """定义一个生成器"""
    total = 0
    nums = []
    while True:
        x = yield
        print(key + '销量:', x)
        if not x:
            break  # 结束while循环
        total += x
        nums.append(x)
    return total, nums


if __name__ == '__main__':
    g = sales_num("苹果手机")
    g.send(None) # 激活生成器, 也可以使用next(g)
    g.send(5000) #  send一个值到生成器内部, 就是x接收的
    g.send(1000) #  send一个值到生成器内部, 就是x接收的
    g.send(5000) #  send一个值到生成器内部, 就是x接收的
    g.send(None) # 这次send(None) 表过结束生成器,生成器会抛出StopIteration异常,这是个正常的异常,然后返回total, nums

 

Traceback (most recent call last):
苹果手机销量: 5000
  File "E:/ws/python/LearnFlask/test/mooic/yield_test.py", line 21, in <module>
苹果手机销量: 1000
    g.send(None)
苹果手机销量: 5000
StopIteration: (11000, [5000, 1000, 5000])
苹果手机销量: None

  

 

为了优雅的结束生成器, 需要try ....  StopIteration....

下面是优雅的结束生成器的代码

def sales_num(key):
    """定义一个生成器"""
    total = 0
    nums = []
    while True:
        x = yield
        print(key + '销量:', x)
        if not x:
            break  # 结束while循环
        total += x
        nums.append(x)
    return total, nums


if __name__ == '__main__':
    g = sales_num("苹果手机")
    g.send(None) # 激活生成器, 也可以使用next(g)
    g.send(5000) #  send一个值到生成器内部, 就是x接收的
    g.send(1000) #  send一个值到生成器内部, 就是x接收的
    g.send(5000) #  send一个值到生成器内部, 就是x接收的
    try:
        g.send(None) # 这次send(None) 表过结束生成器,生成器会抛出StopIteration异常,这是个正常的异常,然后返回total, nums
    except StopIteration as e:
        print(e.value)  # (11000, [5000, 1000, 5000])  通过异常,获取生成器的返回值
苹果手机销量: 5000
苹果手机销量: 1000
苹果手机销量: 5000
苹果手机销量: None
(11000, [5000, 1000, 5000])

 

通过上面的yield from示例可知,yield from帮我们处理了try...stopiteration...异常, 因为我们并没有手动去处理.

posted on 2019-12-27 22:42  显示账号  阅读(202)  评论(0编辑  收藏  举报