ZetCode

Python __ne__ 方法

最后修改于 2025 年 4 月 8 日

本综合指南探讨了 Python 的 __ne__ 方法,这是一个实现“不等于”比较操作的特殊方法。我们将介绍基本用法、与 __eq__ 的关系以及实际示例。

基本定义

当使用 != 运算符时,将调用 __ne__ 方法。 如果对象不相等,它应该返回 True,否则返回 False。 默认情况下,它会委托给 __eq__ 并否定结果。

主要特征:它必须接受两个参数(selfother),应该返回一个布尔值,并且应该与 __eq__ 实现一致的行为。 它是 Python 丰富的比较方法的一部分。

基本 __ne__ 实现

这是一个简单的类,实现了 __eq____ne__ 以演示它们的关系。 该类表示 2D 空间中的一个点。

basic_ne.py
class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y
    
    def __eq__(self, other):
        if not isinstance(other, Point):
            return NotImplemented
        return self.x == other.x and self.y == other.y
    
    def __ne__(self, other):
        return not (self == other)

p1 = Point(1, 2)
p2 = Point(1, 2)
p3 = Point(3, 4)

print(p1 != p2)  # False
print(p1 != p3)  # True

此示例显示了通过否定 __eq__ 来实现 __ne__ 的标准模式。 这确保了相等和不相等比较之间的一致行为。

__eq__ 中的 NotImplemented 返回告诉 Python 尝试以另一种方式进行比较,或者如果类型不兼容则回退到默认行为。

自定义不等式逻辑

有时您可能需要自定义不等式逻辑,而不仅仅是相等性的否定。 这是一个具有版本控制文档类的示例。

custom_ne.py
class Document:
    def __init__(self, content, version):
        self.content = content
        self.version = version
    
    def __eq__(self, other):
        if not isinstance(other, Document):
            return NotImplemented
        return self.content == other.content
    
    def __ne__(self, other):
        if not isinstance(other, Document):
            return NotImplemented
        # Documents are unequal if content differs OR versions differ
        return self.content != other.content or self.version != other.version

doc1 = Document("Hello", 1.0)
doc2 = Document("Hello", 1.1)
doc3 = Document("World", 1.0)

print(doc1 != doc2)  # True (versions differ)
print(doc1 != doc3)  # True (content differs)

在这种情况下,如果文档的内容匹配,则认为文档相等,但如果内容或版本不同,则认为文档不相等。 这表明 __ne__ 可以实现比仅否定 __eq__ 更复杂的逻辑。

当您想要跟踪更改但将某些属性视为不应影响相等比较的元数据时,此模式可能很有用。

继承和 __ne__ 行为

使用继承时,您需要确保 __ne__ 与父类和子类正确配合。 这是一个演示此操作的示例。

inheritance_ne.py
class Animal:
    def __init__(self, name):
        self.name = name
    
    def __eq__(self, other):
        if not isinstance(other, Animal):
            return NotImplemented
        return self.name == other.name
    
    def __ne__(self, other):
        return not (self == other)

class Dog(Animal):
    def __init__(self, name, breed):
        super().__init__(name)
        self.breed = breed
    
    def __eq__(self, other):
        if not isinstance(other, Dog):
            return NotImplemented
        return super().__eq__(other) and self.breed == other.breed

animal = Animal("Buddy")
dog1 = Dog("Buddy", "Labrador")
dog2 = Dog("Buddy", "Poodle")

print(animal != dog1)  # True (different types)
print(dog1 != dog2)    # True (different breeds)

此示例展示了不等式如何与继承一起使用。 Animal 类通过名称实现基本的相等/不等式,而 Dog 添加了品种比较。 父类中的 __ne__ 方法适用于两者。

请注意,animal != dog1 返回 True,因为它们是不同的类型,即使它们共享相同的名称。 这演示了比较方法中的类型检查。

__ne__ 与不同的类型

__ne__ 方法应正确处理与不同类型的比较。 这是一个可以与整数进行比较的类示例。

different_types.py
class RomanNumeral:
    def __init__(self, value):
        self.value = value
    
    def __eq__(self, other):
        if isinstance(other, RomanNumeral):
            return self.value == other.value
        if isinstance(other, int):
            return self.value == other
        return NotImplemented
    
    def __ne__(self, other):
        eq_result = self.__eq__(other)
        if eq_result is NotImplemented:
            return NotImplemented
        return not eq_result

num1 = RomanNumeral(5)
num2 = RomanNumeral(5)
num3 = RomanNumeral(7)

print(num1 != num2)  # False
print(num1 != num3)  # True
print(num1 != 5)     # False
print(num1 != 10)    # True
print(num1 != "V")   # True (falls back to default behavior)

这个 RomanNumeral 类可以与其他实例和整数进行比较。 __ne__ 方法通过委托给 __eq__ 并否定其结果来正确处理所有情况。

当与不兼容的类型(“V”字符串)进行比较时,它返回 NotImplemented,允许 Python 尝试反向操作或使用默认行为。

__ne__ 中的性能优化

对于复杂的对象,您可以通过提前检查不等式来优化 __ne__,而不是始终首先计算完整的相等性。

optimized_ne.py
class Vector:
    def __init__(self, x, y, z):
        self.x = x
        self.y = y
        self.z = z
    
    def __eq__(self, other):
        if not isinstance(other, Vector):
            return NotImplemented
        return self.x == other.x and self.y == other.y and self.z == other.z
    
    def __ne__(self, other):
        if not isinstance(other, Vector):
            return NotImplemented
        # Early exit if any component differs
        if self.x != other.x:
            return True
        if self.y != other.y:
            return True
        if self.z != other.z:
            return True
        return False

v1 = Vector(1, 2, 3)
v2 = Vector(1, 2, 3)
v3 = Vector(1, 0, 3)

print(v1 != v2)  # False
print(v1 != v3)  # True

这个优化的 __ne__ 实现逐个检查组件,并在发现任何差异时立即返回 True。 对于相等计算成本高昂的大型对象,这可以提高性能。

当不等式是常见情况时,优化是最有益的,因为它允许从比较中提前退出。 对于相等的对象,它执行与 __eq__ 相同的工作。

最佳实践

资料来源

作者

我叫 Jan Bodnar,我是一位充满热情的程序员,拥有丰富的编程经验。 我从 2007 年开始撰写编程文章。到目前为止,我已经撰写了 1,400 多篇文章和 8 本电子书。 我拥有超过十年的编程教学经验。

列出所有 Python 教程