zoukankan      html  css  js  c++  java
  • Python之协程(coroutine)

    Python之协程(coroutine)

    标签(空格分隔): Python进阶


    coroutine和generator的区别

    generator是数据的产生者。即它pull data 通过 iteration
    coroutine是数据的消费者。它push data into pipeline 通过 send

    generator的通常用法

    generator的作用是可以作为data pipeline使用.
    例如可以使用coroutine来做filter,
    或者多路的broadcast。

    generator通常是yield和for的运用。
    示例代码1:

    def fib():
        a, b = 0, 1
        while True:
            yield a
            a, b = b, a+b
            
    for i in fib():
        print(i)
        
    

    用yield接收data,通过for循环将每一步data输出。

    下面介绍coroutine, 它的yield接收外部value,而不是保存内部value。

    def grep(pattern):
        print("Searching for", pattern)
        while True:
            line = (yield)
            if pattern in line:
                print line
                
    

    此处的 yield并不包含任何value,它接受外部.send()方法传过来的value.

    search = grep('coroutine')
    next(search)
    # Output: Searching for coroutine
    search.send("I love you")
    search.send("Don't you love me?")
    search.send("I love coroutines instead!")
    # Output: I love coroutines instead!
    
    search.close()
    

    先通过next(),start这个coroutine.
    之后每一次调用send(),将参数通过yield传入line中。同时相当于自动运行.next()到下一个value. 最终调用.close()关闭这个协程。

    示例1:作为filter使用

    import time
    def follow(thefile, target):
        thefile.seek(0,2) # Go to the end of the file
        while True:
            line = thefile.readline()
            if not line:
                time.sleep(0.1) # Sleep briefly
                continue
            target.send(line)
     
      @coroutine
    def printer():
     while True:
        line = (yield)
        print line
        
    @coroutine
    def grep(pattern,target):
        while True:
            line = (yield) # Receive a line
            if pattern in line:
                target.send(line) # Send to next stage
                
    f = open("access-log")
    follow(f,grep('python',printer()))            
    

    dataflow如下:###

    follow将file中的每一行读取,send到coroutine中,grep查找匹配的line,send到下一个coroutine中,printer接收send过来的data,并且输出。 完成整个filter的流程。

    follow()-> grep() : send() 
    grep() -> printer():send()
    

    示例2:作为broadcasting使用

    @coroutine
    def broadcast(targets):
        while True:
            item = (yield)
            for target in targets:
                target.send(item)
            
            
    f = open("access-log")
    p = printer()
    follow(f,
        broadcast([grep('python',p),
        grep('ply',p),
        grep('swig',p)])
    )
    

    这样就将不同的pattern传入到了不同的coroutine中去,达到了broadcast的目的。

    follow-> broadcast: send()
    broadcast -> grep('python'): send()
    broadcast -> grep('ply') : send()
    broadcast -> grep('swig') : send()
    grep('python') -> printer:
    grep('ply')-> printer: 
    grep('swig')-> printer:
    
    

    关于coroutine的更多用法,可见pdf:
    http://www.dabeaz.com/coroutines/Coroutines.pdf


  • 相关阅读:
    设计模式的原则
    List是线程安全的吗?如果不是该怎么办呢?安全的List对性能的影响有多大呢?
    StringBuilder是不是线程安全的?
    并行运算和普通运算之性能比较
    分布式与集群的区别
    sql查询性能分析
    C#代码实现,确保windows程序只有一个实例(instance)
    jQuery UI
    开源框架完美组合之Spring.NET + NHibernate + ASP.NET MVC + jQuery + easyUI 中英文双语言小型企业网站Demo
    整理的一些学习网站资料
  • 原文地址:https://www.cnblogs.com/bradleon/p/6106595.html
Copyright © 2011-2022 走看看