Python 3.x 子类和父类的比较 问题
在两个类之间实现比较方法时,结果与预期不符Python 3.x 子类和父类的比较 问题,python-3.x,pylint,mypy,Python 3.x,Pylint,Mypy,在两个类之间实现比较方法时,结果与预期不符 class A: def __init__(self, name: str) -> None: self.name = name def __eq__(self, other: object) -> bool: if not isinstance(other, A): return NotImplemented return self.name ==
class A:
def __init__(self, name: str) -> None:
self.name = name
def __eq__(self, other: object) -> bool:
if not isinstance(other, A):
return NotImplemented
return self.name == other.name
class B(A):
def __init__(self, name: str, value: int) -> None:
super().__init__(name)
self.value = value
def __eq__(self, other: object) -> bool:
if not isinstance(other, B):
return NotImplemented
return self.name == other.name and self.value == other.value
a = A("a")
b = B("a", 1)
print(a == b) # True
print(b == a) # True
我想要的是,这些具有不同属性的类的不同实例是不相等的,因此我希望在这两种情况下False
我们得到True
的原因是,如果另一个对象不是B的实例,则在的方法中返回NotImplemented
。由于B
是a
的子类,isinstance(B,a)
返回True
解决方案(尝试1)
我们可以使用type(other)is A来代替使用isinstance(other,A)
进行检查:
class A:
def __init__(self, name: str) -> None:
self.name = name
def __eq__(self, other: object) -> bool:
if not type(other) is A:
return NotImplemented
return self.name == other.name
class B(A):
def __init__(self, name: str, value: int) -> None:
super().__init__(name)
self.value = value
def __eq__(self, other: object) -> bool:
if not type(other) is B:
return NotImplemented
return self.name == other.name and self.value == other.value
a = A("a")
b = B("a", 1)
print(a == b) # False
print(b == a) # False
这与预期的一样有效,但mypy不喜欢它:
error: Returning Any from function declared to return "bool" [no-any-return]
error: "object" has no attribute "name" [attr-defined]
error: Returning Any from function declared to return "bool" [no-any-return]
error: "object" has no attribute "name" [attr-defined]
error: "object" has no attribute "value" [attr-defined]
解决方案(尝试2)
据我所知,为了让mypy喜欢这个解决方案,isinstance
检查必须保持不变。因此,我在值比较中添加了类型检查
class A:
def __init__(self, name: str) -> None:
self.name = name
def __eq__(self, other: object) -> bool:
if not isinstance(other, A):
return NotImplemented
return self.name == other.name and type(other) is A
class B(A):
def __init__(self, name: str, value: int) -> None:
super().__init__(name)
self.value = value
def __eq__(self, other: object) -> bool:
if not isinstance(other, B):
return NotImplemented
return self.name == other.name and self.value == other.value and type(other) is B
a = A("a")
b = B("a", 1)
print(a == b) # False
print(b == a) # False
现在mypy对代码没有问题,但pylint仍然不喜欢该解决方案:
C0123: Using type() instead of isinstance() for a typecheck. (unidiomatic-typecheck)
我怎样才能正确地解决这个问题?你已经非常接近了
检查两个对象是否使用同一类的标准过程如下:
如果类型(x)=类型(y):
然而,许多linter会抱怨并要求您使用isinstance
,因为他们认为您也希望子类的计算结果为true。你所能做的就是忽略它们
希望这能解决你的问题
编辑:
您应该能够使用is
而不是=
如果这不能回答您的问题,请道歉。我的大脑处于关闭状态,我可能误解了这个问题。谢谢你的回答。您建议的类型检查将起作用,但mypy和pylint都不会接受此解决方案。我必须添加三条注释才能删除这些消息。这就提出了这样一个问题:这是否真的是一种方法。您可以尝试将对象的\uuuu class\uuuu
属性等同起来。如果我也保持isinstance()
:如果不是isinstance(other,B)或非self.\uuu class\uuuu==other.\uu class\uuuu:返回NotImplemented
。虽然看起来不太好,不是吗?它不是完美的,不是。但是如果你一心想安抚那些衣料,这可能是你唯一的选择。