Python协程一点理解

发布时间:2019-05-23 21:31:54编辑:auto阅读(2177)

    yield

    def test():
        for i in 'abc':
            yield i
        for i in [1, 2, 3]:
            yield i
    
    
    if __name__ == '__main__':
        gen = test()
        print(gen.send(None))
        print(gen.send(None))
        print(gen.send(None))
        print(gen.send(None))
        print(gen.send(None))
        print(gen.send(None))
        print(gen.send(None))
    def test():
        for i in 'abc':
            yield i
        for i in [1, 2, 3]:
            yield i
    
    
    if __name__ == '__main__':
        gen = test()
        for i in gen:
            print(i)

    使用for循环生成器,因为for循环可以捕捉StopIteration异常。

    yield from

    上面的代码也可以用yield from实现

    def test():
        yield from 'abc'
        yield from [1, 2, 3]
    
    
    if __name__ == '__main__':
        gen = test()
        for i in test():
            print(i)

    yield from 后面需要加的是可迭代对象,它可以是普通的可迭代对象,也可以是迭代器,甚至是生成器。

    使用yield from实现实时计算器

    def average_gen():
        """
        子生成器
        """
        average = 0
        total = 0
        count = 0
        while True:
            num = yield average
            if num is None:
                break
            count += 1
            total += num
            average = total / count
        return average, count, total
    
    
    def proxy_gen():
        """
        委派生成器
        """
        while True:
            average, count, total = yield from average_gen()
            print(f'平均值{average}, 计算{count}次, 总和{total}')
    
    
    def client():
        """
        调用端
        """
        calc_average = proxy_gen()
        calc_average.send(None)
        # next(calc_average)
        # 预激活协程
        print(calc_average.send(10))
        print(calc_average.send(20))
        print(calc_average.send(30))
        calc_average.send(None)
        # 关闭协程
    
    
    if __name__ == '__main__':
        client()

    在委派生成器中的while True可以替换成for循环,循环的大小决定调用端可以calc_average.send(None)的次数(第一次预激活也计入)。

    while Truefor循环用来捕捉StopIteration异常,可以查看第一段代码。

    示例

    def average_gen():
        """
        子生成器
        """
        average = 0
        total = 0
        count = 0
        while True:
            num = yield average
            if num is None:
                break
            count += 1
            total += num
            average = total / count
        return average, count, total
    
    
    def proxy_gen():
        """
        委派生成器
        """
        for i in range(2):
            average, count, total = yield from average_gen()
            print(f'平均值{average}, 计算{count}次, 总和{total}')
    
    
    def client():
        """
        调用端
        """
        calc_average = proxy_gen()
        calc_average.send(None)
        # next(calc_average)
        # 预激活协程
        print(calc_average.send(10))
        print(calc_average.send(20))
        print(calc_average.send(30))
        calc_average.send(None)
        # 关闭协程
        print(calc_average.send(10))
        print(calc_average.send(20))
        print(calc_average.send(30))
        calc_average.send(None)
    
    
    if __name__ == '__main__':
        client()

    示例最后会抛出StopIteration异常。

    因为在第二次calc_average.send(None)时,for循环捕捉了一次异常,进入了最后一次循环,在calc_average.send(None)时,for不能再次循环,不能处理StopIteration异常,故抛出。

关键字