zoukankan      html  css  js  c++  java
  • yield from

    1 yield from 

    yield from关键字是在:PEP 380 -- Syntax for Delegating to a Subgenerator 中提出的

    用于生成器将其部分操作委托给另外一个生成器,这允许将包含yield的一段代码分解出来并放在另外一个生成器中,此外,允许子生成器返回一个值,这个值可供委派生成器使用

    from collections import namedtuple
    
    Result = namedtuple("Result", "count average")
    
    li = [40.9, 38.5, 44.3]
    
    
    # 子生成器
    def averager():
        total = 0.0
        count = 0
        average = None
        while True:
            term = yield
            print("====", term)
            if term is None:
                break
            total += term
            count += 1
            average = total / count
        return Result(count, average)
    
    
    # 委派生成器
    def grouper(result, key):
        while True:
            result[key] = yield from averager()
    
    
    # 调用方
    def main():
        results = {}
        group = grouper(results, "kg")
        next(group)  # 调入 委派生成器, 然后调入子生成器,到yield
        for value in li:
            group.send(value)  # 直接传递到子生成器的yield
        group.send(None)
    
        # group.send(None)
        # print(results)
    
    
    if __name__ == "__main__":
        main()

    yield from的主要功能是打开双向通道,把最外层的调用方与最内层的子生成器连接起来,这样二者可以直接发送和产出值,还可以直接传入异常

    yield from 的六个重要意义

    关于yield from 六点重要的说明:

    1. 子生成器产出的值都直接传给委派生成器的调用方(即客户端代码)
    2. 使用send()方法发送给委派生成器的值都直接传给子生成器。如果发送的值为None,那么会给委派调用子生成器的__next__()方法。如果发送的值不是None,那么会调用子生成器的send方法,如果调用的方法抛出StopIteration异常,那么委派生成器恢复运行,任何其他异常都会向上冒泡,传给委派生成器
    3. 生成器退出时,生成器(或子生成器)中的return expr表达式会出发StopIteration(expr)异常抛出
    4. yield from表达式的值是子生成器终止时传给StopIteration异常的第一个参数。yield from 结构的另外两个特性与异常和终止有关。
    5. 传入委派生成器的异常,除了GeneratorExit之外都传给子生成器的throw()方法。如果调用throw()方法时抛出StopIteration异常,委派生成器恢复运行。StopIteration之外的异常会向上冒泡,传给委派生成器
    6. 如果把GeneratorExit异常传入委派生成器,或者在委派生成器上调用close()方法,那么在子生成器上调用clsoe()方法,如果它有的话。如果调用close()方法导致异常抛出,那么异常会向上冒泡,传给委派生成器,否则委派生成器抛出GeneratorExit异常

    2 yield from与async

    import sys
    import time
    
    
    def binary(n):
        if n <= 0:
            return 1
        l = yield from binary(n - 1)
        r = yield from binary(n - 1)
        return l + 1 + r
    
    
    async def abinary(n):
        if n <= 0:
            return 1
        l = await abinary(n - 1)
        r = await abinary(n - 1)
        return l + 1 + r
    
    
    def timeit(func, depth, repeat):
        t0 = time.time()
        for _ in range(repeat):
            o = func(depth)
            print(o)
            try:
                while True:
                    o.send(None)
            except StopIteration:
                pass
        t1 = time.time()
        print('{}({}) * {}: total {:.3f}s'.format(
            func.__name__, depth, repeat, t1 - t0))
    
    
    # timeit(binary, 19, 30)  # binary(19) * 30: total 7.388s
    # timeit(abinary, 19, 30)  # abinary(19) * 30: total 7.357s   # 2着用时基本一致
    学无止境!
  • 相关阅读:
    配置DNS域名解析服务器
    使用buildroot编译bind DNS服务器
    java值得注意的几个问题
    访问权限
    import static与import的区别
    八大排序算法
    移植DNS服务bind
    Sql存储过程中延迟执行
    【转】ado实体数据模型增删改查基本用法
    JS 拖动事件
  • 原文地址:https://www.cnblogs.com/glh-ty/p/11081986.html
Copyright © 2011-2022 走看看