12

我正在使用 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"

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

4

3 回答 3

13

==应该采用任意其他对象,而不仅仅是您类型的对象。如果它不能识别另一个对象,它应该返回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

NotImplemented不是 的实例bool,但 mypy 似乎对此有一个奇怪的特殊情况。它希望返回注释是bool,并且它不会抱怨该return NotImplemented行。

此外,如果您需要MyObject在其自身的正文中引用类型提示,则需要使用字符串,'MyObject'而不是MyObject. MyObject还不存在。

于 2016-06-01T00:10:33.187 回答
3

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

这样做的原因是因为 yourMyObject是 的子类型object,所以 aMyObject可以在任何需要 a 的地方传递,object这意味着该代码可以将它与任何其他 进行比较object,并且类型检查器没有合法的方式来抱怨。所以,为了反映这一点,你__eq__必须写成期望任何object.

您可以做的是在方法体的前面,检查类型并返回(或引发异常):

if not isinstance(other, MyObject):
  return False

然后正如那些文档所说,Mypy 足够聪明,在检查之后,它会知道这other是 aMyObject并相应地对待它。

于 2016-06-01T01:15:58.693 回答
-1

使用“isinstance()”的测试只有在没有继承的情况下才有效,如果有的话,你要么需要在派生类中覆盖eq要么使用 if type(self) != type(other)

于 2020-10-09T09:06:06.547 回答