zoukankan      html  css  js  c++  java
  • Python连载41-yield from详解、委派生成器

    一、

    1.yield from

    (1)调用协程为了得到返回值,协程必须正常终止

    (2)生成器正常终止会发出StopIteration异常,异常对象的value属性保存返回值。

    (3)yield from从内部捕获StopIteration异常

    我们举个例子

    def gen():
    
        for c in "AB":
    
            yield c
    
    #list直接用生成器作为参数
    
    print(list(gen()))
    
    def gen_new():
    
        yield from "AB"
    
    print(list(gen_new())

    解释:我们从中可以看出,两个函数最后返回的结果是一致的,可以用下面的图片来解释它们的运行过程,第二个函数增加了一个管道层,使得这个函数更加灵活;第一个函数中,list向迭代器逐一要值,然后一起输出出来;第二个函数,向管道要值,然后管道收集到所有的迭代数,然后再一并返回给list函数

    2.委派生成器

    (1)包含yield from表达式的生成器函数

    (2)委派生成器在yield from表达式暂停,调用方可以直接把数据发给自生成器

    (3)子生成器再把产出的值发给调用方

    (4)子生成器在最后,解释器会抛出StopIteration,并且把返回值附加到异常对象上

    举个例子:

     
    
    from collections import namedtuple
    
    ResClass = namedtuple("Res","count average")
    
    #子生成器
    
    def average():
    
        total = 0.0
    
        count = 0
    
        average = None
    
    ​
    
        while True:
    
            term = yield
    
            #None是哨兵值
    
            if term is None:
    
                break
    
            total += term
    
            count += 1
    
            average = total/count
    
    ​
    
        return ResClass(count,average)
    
    ​
    
    #委派生成器
    
    def grouper(storages,key):
    
        while True:
    
            #获取averager()返回的值
    
            storages[key] = yield from average()
    
    ​
    
    #客户端代码
    
    def abc():
    
        process_data = {
    
            "boys_2":[39.0,40.8,43.2,43.1,38.6,41.4,40.6,36.3],
    
            "boys_1":[1.38,1.5,1.32,1.25,1.37,1.48,1.25,1.49,1.46]
    
        }
    
        storages = {}
    
        for k,v in process_data.items():
    
            #获取协程
    
            coroutine = grouper(storages,k)
    
            #预激协程
    
            next(coroutine)
    
    ​
    
            #发送数据到协程
    
            for dt in v:
    
                coroutine.send(dt)
    
    ​
    
            #终止协程
    
            coroutine.send(None)
    
        print(storages)
    
    #run
    
    if __name__ == "__main__":
    
        abc()

    #解释:

    #1.外层for循环每次迭代会新建一个grouper实例,赋值给coroutine变量;grouper是委派生成器生成

    #2.调用next(coroutine),预激委派生成器grouper,此时进入while True循环,调用子生成器average

    #3.内层for循环调用coroutine.send(value),直接把值传给子生成器average,同时,当前的grouper

    #4.内层循环结束后,grouper实例依旧在yield from表达式处暂停,因此,grouper函数定义体中

    #5.coroutine.send(None)终止averager子生成器,子生成器抛出StopIteration异常并将返回数组

    二、源码

    d27_4_yield_from_and_delegate_generator.py​

    https://github.com/ruigege66/Python_learning/blob/master/d27_4_yield_from_and_delegate_generator.py

    2.CSDN:https://blog.csdn.net/weixin_44630050(心悦君兮君不知-睿)

    3.博客园:https://www.cnblogs.com/ruigege0000/

    4.欢迎关注微信公众号:傅里叶变换,个人公众号,仅用于学习交流,后台回复”礼包“,获取大数据学习资料

     

  • 相关阅读:
    iOS 关于第三方键盘
    linux分期挂载永久生效
    linux echo 用法 【 -e c 体会】
    expr index
    tail -f 不好用? 用法小解析
    【Linux】su
    Linux 下mv命令使用 目标目录不存在时会更名被目标目录并放在/目录下
    Java一点笔试题【2016-04-13】
    Linux 上重启tomcat 【转】 http://www.cnblogs.com/tovep/articles/2473147.html
    Oracle Merge into [转] [ http://www.cnblogs.com/dongsheng/p/4384754.html]
  • 原文地址:https://www.cnblogs.com/ruigege0000/p/11657891.html
Copyright © 2011-2022 走看看