我想通过子类化将新功能添加到现有的等待类中。
让我们从一个非常简单的基类开始,创建一些对象,这些对象在短暂睡眠后异步返回99。子类应仅将+1添加到结果中。
我找不到使用super()
来引用基类的正确方法。
import asyncio
class R99:
def __await__(self):
loop = asyncio.get_event_loop()
fut = loop.create_future()
loop.call_later(0.5, fut.set_result, 99)
return fut.__await__()
class R100(R99):
async def add1(self):
v = await R99()
#v = await super().__await__() # <== error
return v + 1
def __await__(self):
return self.add1().__await__()
async def test():
print(await R99())
print(await R100())
asyncio.get_event_loop().run_until_complete(test())
答案 0 :(得分:4)
await method必须返回一个迭代器,因此您可以使其成为生成器并使用yield from语法:
class R100(R99):
def __await__(self):
v = yield from super().__await__()
return v + 1
答案 1 :(得分:2)
如果允许您修改R99
,则可以使__await__()
调用实际的协程,该协程可以按常规方式链接到super()
:
import asyncio
class R99:
async def await_coro(self):
loop = asyncio.get_event_loop()
fut = loop.create_future()
loop.call_later(0.5, fut.set_result, 99)
return await fut
def __await__(self):
return self.await_coro().__await__()
class R100(R99):
async def await_coro(self):
v = await super().await_coro()
return v + 1
如果这不是一个选择,@ Vincent的回答恰好说明了如何从一个__await__
链接到另一个。请注意,您以为await
是新的yield from
是正确的-实际上,通常没有理由在新编写的异步代码中使用yield from
。 (这当然不适用于委托给子生成器的与异步无关的生成器;欢迎继续使用yield from
。)
但是,通过实现__await__()
,您将进入使用生成器实现协程的较低级API。在此级别,yield
暂停协程,将控制返回到事件循环,yield from
委托给另一个实现协程的生成器。在新代码中,该层的唯一有效目的是在不使用解释器的情况下实现等待对象。在Python / C或Cython中。通过提供一个返回迭代器的__await__
来完成此操作,如图here所示。结果对象等效于async def
。