用于生成器和协程的异步装饰器

2024-04-20 03:31:24 发布

您现在位置:Python中文网/ 问答频道 /正文

这个问题与synchronous version中的同一个问题有关。 目标是设计一个decorator,它可以将生成器或协程作为参数作为输入。我的代码看起来像:

import asyncio


def say_hello(function):

    async def decorated(*args, **kwargs):
        return_value = function(*args, **kwargs)
        if isinstance(return_value, types.AsyncGeneratorType):
            print("Hello async generator!")
            async for v in return_value:
                yield v
        else:
            print("Hello coroutine!")
            return await return_value

    return decorated


@helpers.say_hello
async def generator():
    for i in range(5):
        await asyncio.sleep(0.2)
        yield i

@helpers.say_hello
async def coroutine():
    await asyncio.sleep(1)
    return list(range(5))


async def test():
    for v in generator():
        print(v)
    for v in coroutine():
        print(v)

这给出的错误是:

^{pr2}$

{{{cda}和

有什么办法可以让它工作吗?(除了在say_hello中有一个参数来指定function是生成器还是协程)。在


Tags: inasynciohelloforasyncreturnvaluedef
1条回答
网友
1楼 · 发布于 2024-04-20 03:31:24

基本上可以使用另一个答案部署的相同机制,但应用于协同程序。例如:

def say_hello(function):
    def decorated(*args, **kwargs):
        function_instance = function(*args, **kwargs)
        if isinstance(function_instance, types.AsyncGeneratorType):
            async def inner():
                print("Hello async generator!")
                async for v in function_instance:
                    yield v
        else:
            async def inner():
                print("Hello coroutine!")
                return await function_instance
        return inner()
    return decorated

注意,在本例中,decorated是使用def而不是{}定义的。这确保了在调用时,它立即开始运行,并能够选择返回的内容,即协程对象上的异步生成器迭代器。由于decorated返回一个通过调用用async def inner定义的函数创建的对象,因此它在功能上等同于async def本身。在

您的test函数是不正确的,因为它使用for来迭代异步生成器,并且它在协程上迭代。相反,它应该是async def,并使用async for迭代异步生成器,await等待协同程序。我使用以下代码进行测试(generatorcoroutine不变):

^{pr2}$

相关问题 更多 >