【问题标题】:Why does defining the argument types for __eq__ throw a MyPy type error?为什么为 __eq__ 定义参数类型会引发 MyPy 类型错误?
【发布时间】:2016-09-30 03:46:44
【问题描述】:

我正在使用 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__ 使用我选择的类型进行类型检查。

【问题讨论】:

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


    【解决方案1】:

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

    【讨论】:

    • Re: 在它自己的正文中引用MyObject,我已经在我的代码的其他地方没有引用,我没有从 MyPy 得到错误:github.com/pirate/py-data/blob/master/…
    • @NickSweeting:你跑了吗? You should get an error when you try to run it.
    • 啊,谢谢@user2357112,我只尝试了 mypy-ing 并忽略了实际运行它。将其更改为字符串有效。
    • 我刚刚意识到的一件事,我以前从未见过函数返回异常类型(而不是raiseing 他们),这是标准做法吗?
    • @NickSweeting:NotImplemented 也不例外。您正在考虑 NotImplementedError。返回 NotImplemented 是您表示您的特殊方法没有为操作指定含义的方式,因此 Python 应该尝试其他对象的方法。我听说这是一个返回值,而不是出于速度目的的异常。
    【解决方案2】:

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

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

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

    if not isinstance(other, MyObject):
      return False
    

    那么作为those docs say,Mypy 足够聪明,在检查之后,它会知道otherMyObject 并相应地对待它。

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-07-18
        • 2021-04-21
        • 2016-11-07
        • 1970-01-01
        • 2014-02-17
        • 1970-01-01
        • 2020-08-31
        相关资源
        最近更新 更多