Typehint *args 用于可变长度异构返回值,如 asyncio.gather()

问题描述 投票:0回答:1

我在这里的类型系统遇到了一些问题。 我需要类似

asyncio.gather()
的东西,其中返回值是协程的返回值,顺序与参数中给出的顺序相同。

async def f1() -> int: ...
async def f2() -> str: ...
async def f3() -> bool: ...

a, b, c = await asyncio.gather(f1(), f2(), f3())

这有效:

  • a
    属于类型
    int
  • b
    属于类型
    str
  • c
    属于类型
    bool

我有一个接受多个

partial[Coroutine[Any, Any, T]]
的函数。

type PartialCoroutine[T] = partial[Coroutine[Any, Any, T]]

async def run runPartialCoroutines[T](*args: PartialCoroutine[T]) -> list[T]: ...

如果我运行我的函数,它只使用第一个函数的返回值

async def f1() -> int: ...
async def f2() -> str: ...
async def f3() -> bool: ...

a, b, c = await runPartialCoroutines(f1(), f2(), f3())

这不起作用:

  • a
    属于类型
    int
  • b
    属于类型
    int
  • c
    属于类型
    int

我明白它为什么这样做,但我似乎找不到办法让它发挥作用。 我已经检查了

asyncio.gather()
的类型提示,但我有一种感觉,类型检查器针对这种情况内置了一些自定义逻辑。 有可能做到这一点吗?

python types python-typing
1个回答
0
投票

答案并不美好。基本上,

typeshed
为最多 6 个参数提供一堆重载,以便静态类型检查器可以做出正确的推断。

@overload
def gather(coro_or_future1: _FutureLike[_T1], /, *, return_exceptions: Literal[False] = False) -> Future[tuple[_T1]]: ...  # type: ignore[overload-overlap]
@overload
def gather(  # type: ignore[overload-overlap]
    coro_or_future1: _FutureLike[_T1], coro_or_future2: _FutureLike[_T2], /, *, return_exceptions: Literal[False] = False
) -> Future[tuple[_T1, _T2]]: ...
@overload
def gather(  # type: ignore[overload-overlap]
    coro_or_future1: _FutureLike[_T1],
    coro_or_future2: _FutureLike[_T2],
    coro_or_future3: _FutureLike[_T3],
    /,
    *,
    return_exceptions: Literal[False] = False,
) -> Future[tuple[_T1, _T2, _T3]]: ...
...
© www.soinside.com 2019 - 2024. All rights reserved.