混合理解(异步+同步)在Python中无法正常工作

2024-06-16 08:38:46 发布

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

我试图通过省略可变列表和替换理解来改进代码。有一个嵌套的“for”迭代器,其内部是异步的。以下是工作代码:

async def get_accumulator_providers(order: OrderDTO) -> Tuple[str, ...]:
    bucket_mapping = await read_config(order)
    result = []
    for bucket in bucket_mapping:
        async for item in dispatch_bucket(order, bucket, bucket_mapping[bucket], frozenset(accumulator_filters)):
            result.append(item)
    return tuple(result)

但当我使用此代码时:

async def get_accumulator_providers(order: OrderDTO) -> Tuple[str, ...]:
    bucket_mapping = await read_config(order)

    return tuple(item for bucket in bucket_mapping async for item in
             dispatch_bucket(order, bucket, bucket_mapping[bucket], frozenset(accumulator_filters)))

我得到这个错误:

 'async_generator' object is not iterable

我的理解有什么问题


Tags: 代码inforgetasyncbucketdeforder
2条回答

正如@VisioN和我发现的here所提到的,问题不是混合异步和同步循环。问题在于使用tuple()连接迭代。使用[]作为列表解决了此问题。实际上,tuple()不是列表理解,而是获取一个生成器并调用“iter”来生成一个tuple。因此,以下代码起作用:

async def get_accumulator_providers(order: OrderDTO) -> Tuple[str, ...]:
bucket_mapping = await read_config(order)

return tuple([item for bucket in bucket_mapping async for item in
         dispatch_bucket(order, bucket, bucket_mapping[bucket], frozenset(accumulator_filters))])

这里的问题是tuple使用同步迭代器协议

尤鲁·塞利万诺夫回答说:

... result = list(await g(i) for i in range(3))

这相当于此代码:

 async def ait():
     for i in range(3):
         v = await g(i)
         yield v

 result = list(ait())

其中ait是一个异步生成器函数。不能使用常规的for x in ...语法对其进行迭代,也不能将其传递给需要同步迭代器的函数(例如list

类似地,对于同步代码:

 a = (i for i in range(3))
 a[0]
 Traceback (most recent call last):
   File "<stdin>", line 1, in <module>
 TypeError: 'generator' object is not subscriptable

其中(for ...)是定义同步发电机的另一种语法

... result = [await g(i) for i in range(3)]

这相当于此代码:

 result = []
 for i in range(3):
     v = await g(i)
     result.append(v)

我同意PEP530对此有点模糊,可以更新。我会调查一下的

也许我们可以让“TypeError:‘async_generator’object is not iterable”错误消息更清楚一点。欢迎提出任何改进意见

I would say that the first case should either behave as a second one, or raise a syntax error.

没有,但我们可以改进错误消息

相关问题 更多 >