"Animal" 的 "foo" 的重载变体没有匹配参数类型 "str"

No overload variant of "foo" of "Animal" matches argument type "str"

我有一个文件 t.py,其中有一个 class Animal 和一个子 class Cat。两者都有方法 foo,它根据布尔值 inplace.

具有不同的 return 类型

这是文件的完整代码:

# t.py

from __future__ import annotations

from typing import TypeVar, Optional, overload, Literal 

CatOrDog = TypeVar("CatOrDog", bound="Animal")


class Animal:
    @overload
    def foo(self: CatOrDog, inplace: Literal[False], bar) -> CatOrDog:
        ...

    @overload
    def foo(self: CatOrDog, inplace: Literal[True], bar) -> None:
        ...

    def foo(
        self: CatOrDog, inplace: bool = False, bar=None
    ) -> Optional[CatOrDog]:
        ...

    def ffill(self) -> Optional[CatOrDog]:
        return self.foo(bar="a")


class Cat(Animal):
    @overload
    def foo(self, inplace: Literal[False], bar) -> Cat:
        ...

    @overload
    def foo(self, inplace: Literal[True], bar) -> None:
        ...

    def foo(self, inplace: bool = False, bar=None) -> Optional[Cat]:
        ...

如果我 运行 mypy 在上面,我得到

$ mypy t.py 
t.py:23: error: No overload variant of "foo" of "Animal" matches argument type "str"
t.py:23: note: Possible overload variants:
t.py:23: note:     def foo(self, inplace: Literal[False], bar: Any) -> Animal
t.py:23: note:     def foo(self, inplace: Literal[True], bar: Any) -> None
Found 1 error in 1 file (checked 1 source file)

如何正确重载 foo,以便我可以调用 self.foo(bar="a")?我已经尝试设置 bar: Any,但那不起作用。

您需要允许其中一个重载使用默认参数,并在 ffill 方法中为 self 设置正确的类型。

作为:

from __future__ import annotations

from typing import TypeVar, Optional, overload, Literal 

CatOrDog = TypeVar("CatOrDog", bound="Animal")


class Animal:
    @overload
    def foo(self: CatOrDog, inplace: Literal[False]=..., bar=...) -> CatOrDog:
        ...

    @overload
    def foo(self: CatOrDog, inplace: Literal[True], bar=...) -> None:
        ...

    def foo(
        self: CatOrDog, inplace: bool = False, bar=None
    ) -> Optional[CatOrDog]:
        ...

    def ffill(self: CatOrDog) -> Optional[CatOrDog]:
        
        return self.foo(bar="a")


class Cat(Animal):
    @overload
    def foo(self, inplace: Literal[False]=..., bar=...) -> Cat:
        ...

    @overload
    def foo(self, inplace: Literal[True], bar=...) -> None:
        ...

    def foo(self, inplace: bool = False, bar=None) -> Optional[Cat]:
        ...

https://mypy-play.net/?mypy=latest&python=3.9&gist=49da369f6343543769eed2060fa61639