美文网首页
python generator和coroutine入门

python generator和coroutine入门

作者: 慢手暗夜 | 来源:发表于2018-09-03 18:17 被阅读0次

    生成器(generator)

    一般的函数return后,函数栈被销毁,下次调用的时候从新开始。生成器函数可以yield一个值,暂停执行,把执行权交给调用函数,当我们获取另一个值得时候,生成器函数可以恢复执行。

    调用生成器函数的时候,我们得到的是一个生成器对象(类似迭代器)。当我们在生成器对象上调用next()便会得到yield返回的值。下面是两个例子,一个是通过next()获取yield值,另一个是通过循环。

    • next()

    code sample:

    def generator_sample():
        yield "Hello"
        yield "World"
    
    
    generator_obj = generator_sample()
    print(generator_obj)
    print(next(generator_obj))
    print(next(generator_obj))
    

    result:

    <generator object generator_sample at 0x00D910B0>
    Hello
    World
    
    • loop
      code sample:
    def generator_sample():
        yield "Hello"
        yield "World"
    
    
    generator_obj = generator_sample()
    print(generator_obj)
    for i in generator_obj:
        print(i)
    

    result:

    <generator object generator_sample at 0x005A10B0>
    Hello
    World
    

    生成器函数的用处:通过迭代而不是一次性获取所有值,避免消耗大内存。可以利用生成器函数返回多个值。

    基于生成器的协程

    通过生成器,我们可以从函数中获取值。那么如何给生成器函数发送值呢?这就是协程的作用。我们可以通过generator对象的send()函数给生成器函数返回一个值。如下示例:

    def coroutine_base_on_generator():
        temp = yield "yes"
        yield temp
    
    
    c_obj = coroutine_base_on_generator()
    print(next(c_obj))
    print(c_obj.send("you are right"))
    

    result:

    yes
    you are right
    

    asyncio module

    从python3.4,引入了asyncio模块,提供了优雅的异步编程接口。但是依然是基于生成器的协程。下面是asyncio module的示例:

    import asyncio
    import datetime
    import random
    
    
    @asyncio.coroutine
    def asyncio_module_sample(num, count):
        i = 0
        while i < count:
            print("Loop: {} Time: {}".format(num, i))
            yield from asyncio.sleep(random.randint(0, 5))
            i += 1
    
    
    loop = asyncio.get_event_loop()
    task1 = loop.create_task(asyncio_module_sample(1, 5))
    task2 = loop.create_task(asyncio_module_sample(2, 5))
    try:
        loop.run_until_complete(asyncio.wait([task1, task2]))
    finally:
        loop.close()
    

    result:

    Loop: 1 Time: 0
    Loop: 2 Time: 0
    Loop: 2 Time: 1
    Loop: 1 Time: 1
    Loop: 2 Time: 2
    Loop: 1 Time: 2
    Loop: 2 Time: 3
    Loop: 2 Time: 4
    Loop: 1 Time: 3
    Loop: 1 Time: 4
    

    async/await

    从python3.5,引入了async/await语法关键字。所以之前的例子可以用async/await方式重写:

    import asyncio
    import datetime
    import random
    
    
    async def async_await_sample(num, count):
        i = 0
        while i < count:
            print("Loop: {} Time: {}".format(num, i))
            await asyncio.sleep(random.randint(0, 5))
            i += 1
    
    
    loop = asyncio.get_event_loop()
    
    try:
        loop.run_until_complete(asyncio.gather(async_await_sample(1, 5), async_await_sample(2, 5)))
    finally:
        loop.close()
    

    result:

    Loop: 1 Time: 0
    Loop: 2 Time: 0
    Loop: 1 Time: 1
    Loop: 2 Time: 1
    Loop: 1 Time: 2
    Loop: 1 Time: 3
    Loop: 2 Time: 2
    Loop: 1 Time: 4
    Loop: 2 Time: 3
    Loop: 2 Time: 4
    

    async/await方式和asyncio module方式在功能上并没有区别,只是语法的差异。但是两者不能混用。

    相关文章

      网友评论

          本文标题:python generator和coroutine入门

          本文链接:https://www.haomeiwen.com/subject/djibwftx.html