协程的三大应用

  • 无限列表

def fib():
     first, second = 0, 1
     yield first
     yield second
     while True:
         third = first + second
         yield third
         first = second
         second = third
  • 管道

import os
import fnmatch
import gzip, bz2

def coroutine(func):
"""自动调用协程的next()函数"""
    def start(*args, **kwargs):
        g = func(*args, **kwargs)
        g.next()
        return g
    return start

@coroutine
def find_files(target):
    while True:
        topdir, pattern = (yield)
        for path, dirname, filelist in os.walk(topdir):
            for name in filelist:
                if fnmatch.fnmatch(name, pattern):
                    target.send(os.path.join(path, name))

@coroutine
def opener(target):
    while True:
        name = (yield)
        if name.endswith('.gz'): f = gzip.open(name)
        elif name.endswith('.bz2'): f = bz2.BZ2File(name)
        else: f = open(name)
        target.send(f)

@coroutine
def cat(target):
    while True:
        f = (yield)
        for line in f:
            target.send(line)

@coroutine
def grep(pattern, target):
    while True:
        line = (yield)
        if pattern in line:
            target.send(line)
@coroutine
def printer():
    while True:
        line = (yield)
        sys.stdout.write(line)
   
finder = find_files(opener(cat(grep('python', printer))))
finder.send('www', 'access-log*')
finder.send('otherwww', 'access-log*')
  • 并发

最好的例子应该是gevent吧,大家有兴趣可以看下源码。基本的原理是,将函数变为协程,每触发I/O阻塞就yield交出控制权,并将事件注册到epoll,当I/O就绪就是用send方法,传入I/O数据,并恢复逻辑。这么描述其实和tornado、nodejs的网络模型很像,但是协程对于程序员更加友好。tornado和nodejs默认还是通过回调函数完成这个事件循环的,这样代码并不直观,但使用协程可以用同步的方式完成回调函数的工作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值