【发布时间】:2019-03-07 08:49:22
【问题描述】:
我正在学习 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
我注意到我们可以通过实现 __await__ (https://docs.python.org/3.6/reference/datamodel.html#awaitable-objects) 来实现 Coroutine 对象。这样我就可以成功删除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()
最后,我想像这样实现没有yield的迭代器:
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 测试过。
【问题讨论】:
-
关于
yield,我认为这是必需的,因为它允许解释器进行上下文切换。 -
可能是的,但我很想知道手写迭代器与 yield 作为协程相比究竟缺少什么。如果我在 __next__() 中返回 None 而不是 asyncio.sleep(1),则循环不会抱怨它并按我的预期工作。
标签: python iterator generator python-asyncio coroutine