我有一个类MyClass,它包含两个成员变量foo和bar:

class MyClass:
    def __init__(self, foo, bar):
        self.foo = foo
        self.bar = bar

我有这个类的两个实例,每个实例都有相同的foo和bar值:

x = MyClass('foo', 'bar')
y = MyClass('foo', 'bar')

然而,当我比较它们是否相等时,Python返回False:

>>> x == y
False

我如何使python认为这两个对象相等?


当前回答

我写了这个,并把它放在我的项目中的test/utils模块中。对于情况下,当它不是一个类,只是计划ol' dict,这将遍历两个对象,并确保

每个属性都与其对应的属性相等 不存在悬空属性(只存在于一个对象上的attrs)

它的大…这一点都不性感……但是,哦,boi,它工作!

def assertObjectsEqual(obj_a, obj_b):

    def _assert(a, b):
        if a == b:
            return
        raise AssertionError(f'{a} !== {b} inside assertObjectsEqual')

    def _check(a, b):
        if a is None or b is None:
            _assert(a, b)
        for k,v in a.items():
            if isinstance(v, dict):
                assertObjectsEqual(v, b[k])
            else:
                _assert(v, b[k])

    # Asserting both directions is more work
    # but it ensures no dangling values on
    # on either object
    _check(obj_a, obj_b)
    _check(obj_b, obj_a)

您可以通过删除_assert并使用普通的ol' assert来稍微清理它,但当它失败时,您得到的消息是非常没有帮助的。

其他回答

当比较对象的实例时,将调用__cmp__函数。

如果==操作符在默认情况下不适用,您总是可以为对象重新定义__cmp__函数。

编辑:

如上所述,__cmp__函数自3.0起已弃用。 相反,你应该使用“丰富比较”方法。

在你的类中实现__eq__方法;就像这样:

def __eq__(self, other):
    return self.path == other.path and self.title == other.title

编辑:如果你想让你的对象比较相等当且仅当它们有相等的实例字典:

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

类的实例与==比较是非相等的。最好的方法是将cmp函数赋给你的类,它会做这些事情。

如果你想通过内容进行比较你可以使用cmp(obj1,obj2)

在你的例子中,cmp(doc1,doc2)如果它们的内容相同,它将返回-1。

你应该实现方法__eq__:

class MyClass:
    def __init__(self, foo, bar):
        self.foo = foo
        self.bar = bar
        
    def __eq__(self, other): 
        if not isinstance(other, MyClass):
            # don't attempt to compare against unrelated types
            return NotImplemented

        return self.foo == other.foo and self.bar == other.bar

现在它输出:

>>> x == y
True

注意,实现__eq__将自动使类的实例不可哈希,这意味着它们不能存储在集和字典中。如果你不是建模一个不可变的类型(例如,如果属性foo和bar可能会在你的对象的生命周期内改变值),那么建议把你的实例保留为不可哈希的。

如果你正在建模一个不可变类型,你还应该实现数据模型钩子__hash__:

class MyClass:
    ...

    def __hash__(self):
        # necessary for instances to behave sanely in dicts and sets.
        return hash((self.foo, self.bar))

一般的解决方案,比如循环__dict__并比较值的想法,是不可取的——它永远不可能真正通用,因为__dict__可能包含不可比较或不可哈希的类型。

注意:在Python 3之前,你可能需要使用__cmp__而不是__eq__。Python 2用户可能还想实现__ne__,因为在Python 2中不会自动创建一个合理的不等式默认行为(即反转相等结果)。

使用setattr函数。当您不能在类本身中添加内容时,例如,当您导入类时,您可能想要使用此方法。

setattr(MyClass, "__eq__", lambda x, y: x.foo == y.foo and x.bar == y.bar)