如何解决mypy:“__add__”的签名与超类型“tuple”不兼容 - 但 __sub__
我正在制作一个简单的向量类,我正在努力理解 mypy 如何处理我的 __add__
和 __sub__
方法(特别是代码 1 与代码中 mypy 输出的差异3 以下)。
代码 1:
from typing import NamedTuple
class Vector(NamedTuple):
x: float
y: float
def __add__(self,other: Vector) -> Vector:
return Vector(self.x + other.x,self.y + other.y)
代码 2:
from typing import NamedTuple
class Vector(NamedTuple):
x: float
y: float
def __add__(self,other: object) -> Vector:
if not isinstance(other,Vector):
return NotImplemented
return Vector(self.x + other.x,self.y + other.y)
代码 3:
from typing import NamedTuple
class Vector(NamedTuple):
x: float
y: float
def __sub__(self,other: Vector) -> Vector:
return Vector(self.x - other.x,self.y - other.y)
error: Signature of "__add__" incompatible with supertype "tuple"
。
第二(这让我更加困惑),为什么我从代码 3 中得到的错误与代码 1 不同?
非常感谢。
编辑
我猜答案是因为超类 NamedTuple
允许加法,但指定第二个参数是类型 object
,代码 2 允许,而代码 1 不允许。
代码 3 可以找到 mypy,因为 NamedTuple
没有实现 __sub__
。
解决方法
Liskov substitution principle (LSP) 声明子类型的对象应始终可用以代替超类型的对象。在这种情况下,超类型是 tuple
,它有一个 __add__
方法接受另一个 tuple
。
在您的代码 #1 中,您覆盖了此 __add__
方法,但您覆盖的方法不能代替原始方法,因为它只接受 Vector
,而不接受任意 {{1} }.所以这违反了 LSP,因此它是一个类型错误。
您的代码 #2 没有错误,因为您重写的 tuple
方法接受任何 __add__
,因此原始方法的任何有效参数也是新方法的有效参数。这意味着可以使用子类型代替超类型,因此不会违反 LSP。
您的代码 #3 没有错误,因为您的 object
方法没有覆盖超类型中的任何方法 - 未定义 __sub__
的减法 - 并且添加新方法不会违反 LSP因为当使用对象代替超类型时,这个新方法根本不会被调用。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。