覆盖超类型的协程时如何使用 mypy?

jua*_*osl 2 python mypy

有一个类扩展了另一个类并覆盖了一个返回迭代器的协程:

class Repository:
     async def run(self, query: Query) -> AsyncIterator[int]:
...

class MyRepository(Repository):
     async def run(self, query: Query) -> AsyncIterator[int]:
...
Run Code Online (Sandbox Code Playgroud)

运行 mypy 返回此错误:

error: Return type "AsyncIterator[int]" of "run" incompatible with return type "Coroutine[Any, Any, AsyncIterator[int]]" in supertype "Repository"
Run Code Online (Sandbox Code Playgroud)

协程的类型与普通函数一样,所以我不确定正确的方法是什么。

使用 ABC 类不会修复它:

class Repository(metaclass=ABCMeta):
    @abstractmethod
    async def run(self, query: Query) -> AsyncIterator[int]:
Run Code Online (Sandbox Code Playgroud)

jua*_*osl 5

由于这个问题找到了它:

我认为你不应该让协议函数 async def,而只是 def。从概念上讲,异步生成器是一个可调用的,它返回一个 AsyncIterator(或更准确地说,一个 AsyncGenerator)。但是一个没有 yield 的 async def 函数返回一个 Awaitable,无论它声明的返回类型是什么,这就是 mypy 解释你的协议的方式。

所以,async def run随着def run作品的变化。