为什么定义__eq__的参数类型会抛出MyPy类型错误?

时间:2016-05-31 23:56:35

标签: python python-3.x types typechecking mypy

我使用的是Python 3.5.1和新发布的MyPy v0.4.1静态类型分析器。

我有一些更复杂的代码,我已经简化为重现错误所需的最简单的python类:

class MyObject(object):
    def __init__(self, value: int=5) -> None:
        self.value = value

    def __eq__(self, other: MyObject) -> bool:
        return self.value == other.value

运行类型检查器mypy test.py会产生以下错误:

test.py: note: In class "MyObject":
test.py:5: error: Argument 1 of "__eq__" incompatible with supertype "object"

我基于these docs的理论是,对象上的__eq____ne__已经定义了类型,这与我的子类重新定义这些类型有冲突。我的问题是如何定义这些类型以确保使用我选择的类型对__eq__进行类型检查。

3 个答案:

答案 0 :(得分:7)

==应该采用任意其他对象,而不仅仅是您类型的对象。如果它无法识别其他对象,则应返回NotImplemented

class MyObject(object):
    def __init__(self, value: int=5) -> None:
        self.value = value

    def __eq__(self, other: object) -> bool:
        if not isinstance(other, MyObject):
            return NotImplemented
        return self.value == other.value

此外,如果您需要在自己的正文中引用MyObject类型提示,则需要使用字符串'MyObject'代替MyObjectMyObject尚不存在。

答案 1 :(得分:3)

您对文档的阅读是正确的 - 您需要为方法(__eq__)提供与基类(object)中相同的签名,或者更宽松的方法

原因是因为您的MyObject是[{1}}的子类型,object可以传递到任何需要MyObject的地方......这意味着该代码可以将其与任何其他object进行比较,并且类型检查器没有合法的方式进行投诉。因此,为了反映这一点,您必须编写object以期望任何__eq__

你可以做的是在方法的正文中,检查类型并返回(或引发异常):

object

然后作为those docs say,Mypy非常聪明,在检查之后,它会知道if not isinstance(other, MyObject): return False other并相应地对待它。

答案 2 :(得分:-1)

使用“ isinstance()”的测试仅在没有继承的情况下才有效,如果存在继承,则您需要在派生类中重写 eq 或使用type(self)!= type(other)