倒行逆施:
“西狂” 杨过所创 黯然销魂掌 第十七式
掌法逆中有正,正反相冲,自相矛盾,不能自圆其说
出掌时需要 头下脚上,倒过身子,源自 “西毒” 欧阳锋

在我们定义一个类的时候,常常想要将这个类实例化的多个对象之间进行比较,一般情况下,当两个对象中的属性一致的时候,我们会认为这两个对象是相等。

class Person:
    def __init__(self, name, gender):
        self.name = name
        self.gender = gender
        
a = Person('小红', '女')
b = Person('小红', '女')

print(a == b)        # False
print(id(a), id(b))  # 84716680 84716872

在上边这段代码中,我们使用同一个类实例化了两个对象,这两个对象的属性完全一致,当我们使用 == 进行判断时,却得到了 False ,这是因为 == 默认会使用 内存地址 进行比较,那么我们能否重新实现这部分判断的逻辑呢?

__eq__ 方法

这时候我们就需要用到 __eq__() 魔法方法了,该方法定义了比较运算符 == 的行为,重写该方法来完成我们自己的比较逻辑了!

def __eq__(self, other):
    return self.__dict__ == other.__dict__

经过简单的重写后,我们的代码就可以按照预定的思路正确运行了。然而,还有一个严重的问题 …

  • None 进行比较

    当我们使用 Person 创建出来的实例和 None 值进行比较的时候,此时便发生了如下错误:AttributeError: 'NoneType' object has no attribute 'name'


None 值进行比较时,None 被传递给了 other,随后又在 if 语句中访问了 othername 属性,但是一个 None 怎么会有 name 属性呢?这也是我们代码报错的原因,明白原因后,我们便开始继续改造代码:

    def __eq__(self, other):
	    if isinstance(other, Person):  # 判断 other 是否为Person类实例化的对象
	         if self.name == other.name and self.gender == other.gender:  # 若是, 在进行判断
	             return True
	         else:
	             return False
	     else:
	         return NotImplemented

return NotImplemented 作用:

此时会向 python解释器发出一个信号, 当前无法进行比较, 请尝试其他可行方法

此处解释器 会调用 父类(object)中 __eq__ 方法进行比较

__ne__ 方法

除了上边的 问题外 ,还有一点需要注意,当我们仅仅实现了 __eq__ 方法,却没有实现 __ne__方法时,如果我们进行 != 判断,那么默认会委托给 __eq__() 并对结果取反,为避免出现意外的问题,建议同时 重写 eqne 两个方法

参考