代码之家  ›  专栏  ›  技术社区  ›  Kamyar

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

  •  0
  • Kamyar  · 技术社区  · 4 年前

    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
    

    0 回复  |  直到 4 年前
        1
  •  1
  •   alex_noname    4 年前

    tuple 使用同步迭代器协议。

    尤鲁·塞利万诺夫回答 here

    ... 结果=列表(等待范围(3)内的i的g(i))

    这相当于此代码:

     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”错误消息更清楚一点。欢迎提出任何改进意见。

    我想说,第一种情况要么表现为第二种情况,要么引发语法错误。

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

        2
  •  0
  •   Kamyar    4 年前

    如前所述@VisioN和我发现 here

    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))])