zoukankan      html  css  js  c++  java
  • Python 进阶 之 协程

    协程的概念级描述(与线程对比):转自知乎 链接

      线程有两个必须要处理的问题:一是碰着阻塞式IO会导致整个进程被挂起;

                    二是由于缺乏时钟阻塞,进程需要自己拥有调度线程的能力。

      如果一种实现使得每个线程需要自己通过调用某个方法,主动交出控制权。那么我们就称这种线程是协作式的,即是协程。

    在Python中关于协程的实现方式有三种:

    1. 最初的生成器变形yield/send
    2. 引入@asyncio.coroutine和yield from
    3. 在Python3.5版本中引入async/await关键字

    以下代码均在Centos 7 Python3.6调试通过!

    简单的yield使用描述:

    def fun():
        index = 0
        while True:
            yield index
            index += 1
            if index > 3 :
                break
    for i in fun():
        print (i)
    输出:0 1 2 3

    在此例中yield做的事是:

      1:将函数fun的返回值设定为一个生成器

      2:每次运行至yield index 时会将index的值作为生成器的下一个元素返回值for循环并且被赋值给变量i,用print输出出来

    简单的yield/send使用描述:

    def fun():
        index = 0
        while True:
            value = yield index
            print ("value=" + str(value))
            print ("index=" + str(index))
            index += 1
            if index > 3 :
                break
    funobj = fun()
    print (type(funobj))
    print ("next=" + str(next(funobj)))
    for i in funobj:
        print ("i=" + str(i))
        try:
            funobj.send(i+100)
        except StopIteration:
            print("it's stop")
    输出:

    <class 'generator'>
    next=0
    value=None
    index=0
    i=1
    value=101
    index=1
    value=None
    index=2
    i=3
    value=103
    index=3
    it's stop

    不是很精通,因此代码有点乱。

    解释:

      首先声明了fun函数,并将fun赋给了对面funobj,funobj是一个迭代器。next(funobj)初始化并启动迭代器,程序开始运行fun函数至value = yield index(第一次)结束,yield返回了第一个index值0 next=0

      for i in funobj:启动迭代器,因此此时send还未传值,因此value和next都是空,value=None index=0 程序运行fun函数至value = yield index(第二次)结束,yield返回了第二个index值1 i=1

      注意之后send发送了值101,for再次启动迭代器,从yield启动时捕获到此值101,value=101 index=101。此后类似。

      迭代器结束时会捕获到 StopIteration异常,将此捕获并输出出来 it's stop

    简单的yield/send使用描述:

      yeild from语法就是将生成器函数中包括yield语句的部分逻辑封装到一个子生成器函数中。然后在子生成器函数外面可以做一些其他的业务逻辑。整个生成器函数(包括子生成器函数)对外就是一个生成器函数。

    def fun():
        index = 0
        while True:
            value = yield index
            print ("value=" + str(value))
            print ("index=" + str(index))
            index += 1
            if index > 3 :
                break
    
    def fun2():
        print ("before ")
        yield from fun()
        print ("end ")
    
    funobj = fun2()
    print (type(funobj))
    print ("next=" + str(next(funobj)))
    for i in funobj:
        print ("i=" + str(i))
        try:
            funobj.send(i+100)
        except StopIteration:
            print("it's stop")

    输出:

    <class 'generator'>
    before 
    next=0
    value=None
    index=0
    i=1
    value=101
    index=1
    value=None
    index=2
    i=3
    value=103
    index=3
    end 
    it's stop

     简单的asyncio.coroutine使用描述:(参考自廖雪峰的官方网站

    @asyncio.coroutine通过装饰器调用,作用是把一个generator标记为coroutine类型:

    import asyncio
    
    @asyncio.coroutine
    def hello():
        print("Hello world!")
        # 异步调用asyncio.sleep(1):
        r = yield from asyncio.sleep(1)
        print("Hello again!")
    
    # 获取EventLoop:
    loop = asyncio.get_event_loop()
    # 执行coroutine
    loop.run_until_complete(hello())
    loop.close()

    输出:

    Hello world!
    Hello again!

    简单的asyncawait使用描述:

      asyncawait是针对coroutine的新语法,要使用新的语法,只需要做两步简单的替换:

    1. @asyncio.coroutine替换为async
    2. yield from替换为await

      示例代码:

    import asyncio
    
    async def hello():
        print("Hello world!")
        r = await asyncio.sleep(1)
        print("Hello again!")
    
    # 获取EventLoop:
    loop = asyncio.get_event_loop()
    # 执行coroutine
    loop.run_until_complete(hello())
    loop.close()

      需要注意的是asyncawait只能用在Python 3.5以及后续版本,如果使用3.4版本,则仍需使用asyncio.coroutine和yield from方案。

      示例可能出现的报错如下:

    [root@jans test]# python3.6 c.py 
    Hello world!
    Hello again!
    [root@jans test]# python3.4 c.py 
      File "c.py", line 3
        async def hello():
                ^
    SyntaxError: invalid syntax
  • 相关阅读:
    Delphi的类和对象(九)- 类运算符as、is
    delphi中as,is关键字是如何工作的?
    delphi 中 as 和 is 的使用
    甘超波:NLP发问技巧
    甘超波:NLP如何挖掘信念
    甘超波:NLP自我价值感
    甘超波:NLP次感元
    甘超波:NLP前提假设之每个人都有足够资源,能达成成功的资源
    甘超波:NLP十二条前提假设之重复旧的行为,只会得到旧的结果
    甘超波:NLP十二条前提假设之诺要求知、必须行动
  • 原文地址:https://www.cnblogs.com/JansXin/p/7841369.html
Copyright © 2011-2022 走看看