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
。虽然看起来不太好,不是吗?它不是完美的,不是。但是如果你一心想安抚那些衣料,这可能是你唯一的选择。