我应该如何在__init__中定义一个依赖于协程的变量?

2Cu*_*bed 1 python python-3.x python-asyncio python-3.5

在课堂上Wizard,我想将属性设置wand为coroutine返回的值magic.

class Wizard:
    async def acquire_wand(self):
        self.wand = await magic()
Run Code Online (Sandbox Code Playgroud)

但是,这段代码被认为是"糟糕的Python",因为wand它没有被定义__init__.但是我无法定义它__init__,因为它await可能只用于async繁琐的函数.

class Wizard:
    def __init__(self):
        self.wand = None

    async def acquire_wand(self):
        self.wand = await magic()

    async def perform_spell(self):
        if self.wand is None:
            await self.acquire_wand()
        self.wand.wave()
Run Code Online (Sandbox Code Playgroud)

我可以设置wandNone__init__和使用if self.wand is None:的地方访问它,但这似乎混乱和不便.

我怎样才能确保wand在整个班级中定义?

And*_*lov 5

从技术上讲,有一个覆盖__new__方法的技巧:

class InitCoroMixin:
    """ Mixin for create initialization coroutine
    """
    def __new__(cls, *args, **kwargs):
        """ This is magic!
        """
        instance = super().__new__(cls)

        @asyncio.coroutine
        def coro():
            instance.__init__(*args, **kwargs)
            yield from instance.__ainit__()
            return instance

        return coro()

    @asyncio.coroutine
    def __ainit__(self):
        raise NotImplementedError
Run Code Online (Sandbox Code Playgroud)

请参阅aiohttp_traversal代码以获取完整示例.

但我强烈反对这种方法:在构造函数中使用I/O通常是一个坏主意,请考虑一下.