为什么定义 __eq__ 的参数类型会引发 MyPy 类型错误?
Why does defining the argument types for __eq__ throw a MyPy type error?
我正在使用 Python 3.5.1 和新发布的 MyPy v0.4.1 静态类型分析器。
我有一些更复杂的代码,我已将其简化为最简单的代码 python class 需要重现错误:
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__
已经定义了类型,这与我的子class 对这些的重新定义相冲突类型。我的问题是如何定义这些类型以确保 __eq__
是用我选择的类型进行类型检查的。
==
应该接受任意其他对象,而不仅仅是您类型的对象。如果它不能识别另一个对象,它应该 return 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 似乎有一个奇怪的特例。它希望 return 注释为 bool
,并且不会抱怨 return NotImplemented
行。
此外,如果您需要参考 MyObject
以获取其自身内部的类型提示,则需要使用字符串 'MyObject'
而不是 MyObject
。 MyObject
还不存在。
您对文档的阅读是正确的——您需要为方法 (__eq__
) 提供与基础 class (object
) 中已有的相同的签名,或者更宽松的。
原因是因为您的 MyObject
是 object
的子类型,所以 MyObject
可以传递到任何需要 object
... 的地方意味着该代码可以将它与任何其他 object
进行比较,并且类型检查器没有合法的方式来抱怨。因此,为了反映这一点,您的 __eq__
必须写成期望任何 object
.
你可以做的是在方法主体的前面,检查类型和return(或引发异常):
if not isinstance(other, MyObject):
return False
然后作为 those docs say,Mypy 足够聪明,在检查之后,它会知道 other
是一个 MyObject
并相应地对待它。
只有在没有继承的情况下,使用“isinstance()”的测试才有效,如果有,您需要覆盖派生的 类 中的 eq 或使用 if type (自我)!=类型(其他)
我正在使用 Python 3.5.1 和新发布的 MyPy v0.4.1 静态类型分析器。
我有一些更复杂的代码,我已将其简化为最简单的代码 python class 需要重现错误:
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__
已经定义了类型,这与我的子class 对这些的重新定义相冲突类型。我的问题是如何定义这些类型以确保 __eq__
是用我选择的类型进行类型检查的。
==
应该接受任意其他对象,而不仅仅是您类型的对象。如果它不能识别另一个对象,它应该 return 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 似乎有一个奇怪的特例。它希望 return 注释为 bool
,并且不会抱怨 return NotImplemented
行。
此外,如果您需要参考 MyObject
以获取其自身内部的类型提示,则需要使用字符串 'MyObject'
而不是 MyObject
。 MyObject
还不存在。
您对文档的阅读是正确的——您需要为方法 (__eq__
) 提供与基础 class (object
) 中已有的相同的签名,或者更宽松的。
原因是因为您的 MyObject
是 object
的子类型,所以 MyObject
可以传递到任何需要 object
... 的地方意味着该代码可以将它与任何其他 object
进行比较,并且类型检查器没有合法的方式来抱怨。因此,为了反映这一点,您的 __eq__
必须写成期望任何 object
.
你可以做的是在方法主体的前面,检查类型和return(或引发异常):
if not isinstance(other, MyObject):
return False
然后作为 those docs say,Mypy 足够聪明,在检查之后,它会知道 other
是一个 MyObject
并相应地对待它。
只有在没有继承的情况下,使用“isinstance()”的测试才有效,如果有,您需要覆盖派生的 类 中的 eq 或使用 if type (自我)!=类型(其他)