输入提示协程函数的正确方法是什么?

win*_*win 24 python coroutine type-hinting python-asyncio

我无法理解暗示 a 的类型Coroutine。据我了解,当我们声明一个函数时,如下所示:

async def some_function(arg1: int, arg2: str) -> list:
    ...
Run Code Online (Sandbox Code Playgroud)

我们有效地声明了一个函数,它返回一个协程,当等待时,它返回一个列表。因此,输入提示的方法是:

f: Callable[[int, str], Coroutine[???]] = some_function
Run Code Online (Sandbox Code Playgroud)

Coroutine泛型类型有 3 个参数!如果我们转到该typing.py文件,我们就可以看到它:

...
Coroutine = _alias(collections.abc.Coroutine, 3)
...
Run Code Online (Sandbox Code Playgroud)

还有一种Awaitable类型,从逻辑上讲,它应该是Coroutine只有一个泛型参数的父级(我想是返回类型):

...
Awaitable = _alias(collections.abc.Awaitable, 1)
...
Run Code Online (Sandbox Code Playgroud)

因此,也许以这种方式键入提示函数或多或少是正确的:

f: Callable[[int, str], Awaitable[list]] = some_function
Run Code Online (Sandbox Code Playgroud)

或者是吗?

所以,基本上,问题是:

  1. 在类型提示函数的情况下可以使用Awaitable代替吗?Coroutineasync def
  2. 泛型类型的正确参数是什么Coroutine?它的用例是什么?

isa*_*tfa 14

正如文档所述:

CoroutineABC的对象和实例Coroutine都是AwaitableABC 的实例。

对于Coroutine类型:

的通用版本collections.abc.Coroutine。类型变量的方差和顺序对应于 的方差和顺序Generator

Generator依次有签名Generator[YieldType, SendType, ReturnType]。因此,如果您想保留该类型信息,请使用Coroutine, 否则Awaitable就足够了。


Luk*_*ell 13

Coroutine类型采用与该类型相同的签名Generator

Generator[YieldType, SendType, ReturnType]

由于对协程的未等待调用的结果是可等待的(它可以在表达式中使用await),因此可以使用以下方式对其进行类型提示:

Awaitable[ReturnType]

例子:

async def some_function(arg1: int, arg2: str) -> List[str]:
    return ['foo']

coro: Awaitable[List[str]] = some_function(1, 'bar')
result = await coro
print(result)
# prints ['foo']
Run Code Online (Sandbox Code Playgroud)

然而,对于暗示协程的类型,我认为它们本身都没有用处。相反,我选择与您在上一个示例中所述类似的内容:

def return_coro() -> Callable[[int, str], Awaitable[List[str]]]:
    async def some_function(arg1: int, arg2: str) -> List[str]:
        return ['foo']
    return some_function
Run Code Online (Sandbox Code Playgroud)

请注意,如果您尝试将其传递给明确需要协程的函数(例如 asyncio.run()),mypy 会感到不安。