大多数魔法方法并不是为了与async def
/await
- 一般来说,你应该只使用await
在专用的异步魔术方法中 -__aiter__
, __anext__
, __aenter__
, and __aexit__
。在其他魔术方法中使用它根本不起作用,就像这样__init__
(除非您使用此处其他答案中描述的一些技巧),或者将迫使您始终在异步上下文中使用触发魔术方法调用的任何内容。
现存的asyncio
库倾向于通过以下两种方式之一来处理这个问题:首先,我已经看到使用的工厂模式(asyncio-redis https://github.com/jonathanslenders/asyncio-redis/blob/master/asyncio_redis/pool.py#L27, 例如):
import asyncio
dsn = "..."
class Foo(object):
@classmethod
async def create(cls, settings):
self = cls()
self.settings = settings
self.pool = await create_pool(dsn)
return self
async def main(settings):
settings = "..."
foo = await Foo.create(settings)
其他库使用顶级协程函数来创建对象,而不是工厂方法:
import asyncio
dsn = "..."
async def create_foo(settings):
foo = Foo(settings)
await foo._init()
return foo
class Foo(object):
def __init__(self, settings):
self.settings = settings
async def _init(self):
self.pool = await create_pool(dsn)
async def main():
settings = "..."
foo = await create_foo(settings)
The create_pool
函数来自aiopg
你想打电话的__init__
实际上正在使用这个确切的模式。
这至少解决了__init__
问题。我还没有见过在野外进行异步调用的类变量,所以我不知道是否出现了任何成熟的模式。