Как использовать super () в ожидаемом подклассе? - PullRequest
0 голосов
/ 02 октября 2018

Я бы хотел добавить новую функциональность в существующий ожидаемый класс, создав его подклассы.

Давайте начнем с очень простого базового класса, создающего объекты, которые асинхронно возвращают 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())

Ответы [ 2 ]

0 голосов
/ 03 октября 2018

Если вам разрешено изменять 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__, который возвращает итератор, как показано здесь .Полученный объект эквивалентен async def.

0 голосов
/ 02 октября 2018

Метод await должен возвращать итератор, чтобы вы могли сделать его генератором и использовать yield из синтаксиса :

class R100(R99):

    def __await__(self):
        v = yield from super().__await__()
        return v + 1
...