【问题标题】:No overload variant of "foo" of "Animal" matches argument type "str"“Animal”的“foo”没有重载变体匹配参数类型“str”
【发布时间】:2021-05-31 05:35:54
【问题描述】:

我有一个文件t.py,它有一个类Animal 和一个子类Cat。两者都有方法foo,根据布尔值inplace的值有不同的返回类型。

这是文件的完整代码:

# 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,但不起作用。

【问题讨论】:

    标签: python mypy static-typing


    【解决方案1】:

    您需要允许其中一个重载的默认参数,并在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

    【讨论】:

    • 感谢@sebastian-kreft - 在Literal[True] 过载中,我不需要bar=...,对吗?在两个重载之一中我只需要=...
    • @ignoring_gravity 在Literal[True] 的情况下你仍然需要bar=...,因为bar 是可选的。如果您不指定它,那么 self.foo(True) 将具有最通用的类​​型。
    • 如果 bar=None 在定义中出现在 inplace=False 之前呢?然后我不能有bar=..., inplace: Literal[True],因为非默认将遵循默认
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-15
    • 1970-01-01
    • 1970-01-01
    • 2023-03-06
    • 1970-01-01
    相关资源
    最近更新 更多