Python协程可以在没有await或yield的情况下实现吗?

2024-01-09

我正在学习Python的await/async语法,想知道如何在没有async、await或yield的情况下实现协程。例如,我使用 async def 语法制作了这个简单的三秒计时器:

import asyncio

async def coroutine():
    count = 0
    while count < 3:
        count += 1
        print(count)
        await asyncio.sleep(1)

loop = asyncio.get_event_loop()
loop.run_until_complete(coroutine())
loop.close()

结果:

1
2
3

我注意到我们可以通过实现来实现 Coroutine 对象__await__ (https://docs.python.org/3.6/reference/datamodel.html#awaitable-objects https://docs.python.org/3.6/reference/datamodel.html#awaitable-objects)。这样我就可以成功删除await.

import asyncio

class Generator():
    def __await__(self):
        count = 0
        while count < 3:
            count += 1
            print(count)
            yield from asyncio.sleep(1)

loop = asyncio.get_event_loop()
loop.run_until_complete(Generator())
loop.close()

最后,我想实现没有产量的迭代器,如下所示:

import asyncio

class Iterator():

    def __init__(self):
        self.count = 0

    def __iter__(self): return self

    def __await__(self): return self

    def __next__(self):
        if self.count < 3:
            self.count += 1
            print(self.count)
            return next(asyncio.sleep(1))
        else:
            raise StopIteration()

loop = asyncio.get_event_loop()
result = loop.run_until_complete(Iterator())
loop.close()

但这没有用。显示“1”后停止。

我知道这没有任何实用价值,但我想知道它以正确理解 asyncio。我可以在没有await或yield的情况下实现协程吗?如果是的话该怎么办呢?我用Python 3.6.7测试过。


当协程被实现时using生成器、协程are not发电机:

import asyncio
from typing import Generator


def gen():
    yield 1


async def coro():
    pass


print(isinstance(gen(), Generator))   # True
print(isinstance(coro(), Generator))  # False

这是有意为之的,因为生成器只不过是协程的实现细节。迭代器也是如此:协程are not迭代器。

loop.run_until_complete期望收到一些等待的东西,例如asyncio协程或未来。您试图传递迭代器 - 具有不同行为的不同对象。


长话短说,如果你想实现兼容的协程asyncio:

  • 定义函数async def
  • 或实施__await__魔术方法

并阅读异步文档 https://docs.python.org/3/library/asyncio.html举些例子。

如果您想了解协程如何在非常低级别上工作的一般思想,您可以遵循此优秀的视频 https://www.youtube.com/watch?v=MCs5OvhV9S4David Beazley 从头开始​​实现协程和事件循环。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Python协程可以在没有await或yield的情况下实现吗? 的相关文章

随机推荐