发布于 2018-09-16 22:37:06
你应该只使用__init__。您首先创建一个常规类实例,然后等待该实例。这是两个不同的行动。
例如,您可以先创建实例,然后单独地等待它:
my_class = MyClass(my_parameter)
result_from_coroutine = await my_class或者您可以从它创建一个任务,并让事件循环执行它
my_class = MyClass(my_parameter)
task = asyncio.create_task(my_class) # the loop will await the task
# ...
if task.done():
result_from_coroutine = task.result()__await__方法是await或事件循环用来驱动协同线的方法。同样的分离也适用于coroutine函数(用async def定义);当您调用它们时,它们也会创建一个新的coroutine对象,您不必立即等待它们。您可以在其他时间对结果使用await。
如果您正在寻找异步实例创建,那么您可以通过将方法设置为一个协同机制来破解这个问题:
>>> class Async:
... async def __new__(cls):
... instance = super().__new__(cls)
... return instance
...
>>> Async()
<coroutine object Async.__new__ at 0x103654148>在协同线上等待将创建实际实例并返回它。
考虑到这确实意味着__init__方法将被跳过;后者只有在__new__方法直接返回类的实例(或子类)时才会调用,而coroutine不是这样的实例。您必须亲自明确地这样做:
class Async:
async def __new__(cls, *args, **kwargs):
instance = super().__new__(cls)
instance.__init__(*args, **kwargs)
return instance此时,您也可以决定将__init__方法作为一个协同线。
请注意,这确实有悖常理。我会把呼叫依赖的协同线推迟到稍后的时间。
例如,您只需将参数存储到实例上的类,并在等待实例时使用这些参数(通过调用__await__ ),就像链接到建议执行的post一样。
发布于 2018-09-17 06:53:51
换句话说,我希望能够做
my_class = await MyClass(my_parameter),但是我无法使它以任何方式工作。
通过实现MyClass,您可以使__await__成为可接受的
class MyClass:
def __init__(self, delay):
self.delay = delay
async def __await__(self):
await asyncio.sleep(self.delay)
asyncio.run(MyClass(2)) # sleeps 2 seconds链接答案中的代码做了类似的事情,但是它更复杂,因为它假设__init__本身需要await。如果情况并非如此,而且您的__init__实际上是微不足道的,但是您希望返回的实例是可接受的,则不需要增加拆分初始化的复杂性。
注意:尽管是推荐,asyncio.run()仍然被标记为临时的。在上面的例子中,可以很容易地用run_until_complete替换它。
https://stackoverflow.com/questions/52358908
复制相似问题