一尘不染

如何在__init__中设置带有等待的类属性

python

如何await在构造函数或类主体中定义类?

例如我想要的:

import asyncio

# some code


class Foo(object):

    async def __init__(self, settings):
        self.settings = settings
        self.pool = await create_pool(dsn)

foo = Foo(settings)
# it raises:
# TypeError: __init__() should return None, not 'coroutine'

或具有类body属性的示例:

class Foo(object):

    self.pool = await create_pool(dsn)  # Sure it raises syntax Error

    def __init__(self, settings):
        self.settings = settings

foo = Foo(settings)

我的解决方案(但我希望看到更优雅的方式)

class Foo(object):

    def __init__(self, settings):
        self.settings = settings

    async def init(self):
        self.pool = await create_pool(dsn)

foo = Foo(settings)
await foo.init()

阅读 140

收藏
2020-12-20

共1个答案

一尘不染

最神奇的方法不旨在与工作async def/ await-在一般情况下,你应该只使用await专用异步魔术方法里面-
__aiter____anext____aenter____aexit__。在其他魔术方法中使用它或者根本无法正常工作__init__(除非您使用此处其他答案中描述的一些技巧),否则将迫使您始终在异步上下文中使用任何触发魔术方法调用的方法。

现有的asyncio库通常以以下两种方式之一来处理此问题:首先,我已经看到了使用的工厂模式(asyncio- redis例如):

import asyncio

dsn = "..."

class Foo(object):
    @classmethod
    async def create(cls, settings):
        self = Foo()
        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)

create_pool要从aiopg中调用的函数__init__实际上正在使用此确切模式。

这至少解决了这个__init__问题。我还没有看到可以在野外进行异步调用的类变量,所以我不知道会出现任何完善的模式。

2020-12-20