我在这里的类型系统遇到了一些问题。 我需要类似
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()
的类型提示,但我有一种感觉,类型检查器针对这种情况内置了一些自定义逻辑。
有可能做到这一点吗?
答案并不美好。基本上,
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]]: ...
...