我有一个简单的基类,如下:
class Base:
def get(self, *names: str) -> Any:
# implementation not important
在某些用例中,我试图定义一个具有更严格类型的子类:
from typing import overload, Any
from typing_extensions import Literal
class Sub(Base):
# mypy error here: Signature of "get" incompatible with supertype "Base"
@overload
def get(self, *names: Literal['Something']) -> Something: ...
@overload
def get(self, *names: Literal['Else']) -> Else: ...
def get(self, *names: str) -> Any:
return super().get(*names)
但是,我得到上面的代码Signature of "get" incompatible with supertype "Base"
中指出的错误。我为Sub
类的重载参数尝试了其他形式,但是所有形式都会产生类似的错误。
对于采用*args
的基类方法,无论如何,传入字面值时在子类中提供特定的重载吗?
答案 0 :(得分:0)
Sub
的正确键入应如下所示:
class Sub(Base):
@overload
def get(self, __name: Literal['Something']) -> Something: ...
@overload
def get(self, __name: Literal['Else']) -> Else: ...
@overload
def get(self, *names: str) -> Any: ...
def get(self, *names: str) -> Any:
return super().get(*names)
与问题相比,这里有一些更改。
1)我们定义了一个额外的重载,其类型与实现相同。 python docs for @overload
对此进行了解释:“ [non- @ overload-decorated定义]在运行时使用,但应由类型检查器忽略。”
2)没有人会多次传递相同的文字,因此我们最好将*names
更改为__name
。前导下划线表示name
是“仅限位置”的,如in the mypy docs所述:
# An argument can be declared positional-only by giving it a name
# starting with two underscores:
def quux(__x: int) -> None:
pass
quux(3) # Fine
quux(__x=3) # Error
进行了上述更改后,可以根据需要对Sub
类进行类型检查。