我有一个类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认为这两个对象相等?


当前回答

在Python 3.7(及以上版本)中的数据类中,对象实例的相等性比较是一个内置特性。

Python 3.6提供了数据类的后端端口。

(Py37) nsc@nsc-vbox:~$ python
Python 3.7.5 (default, Nov  7 2019, 10:50:52) 
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from dataclasses import dataclass
>>> @dataclass
... class MyClass():
...     foo: str
...     bar: str
... 
>>> x = MyClass(foo="foo", bar="bar")
>>> y = MyClass(foo="foo", bar="bar")
>>> x == y
True

其他回答

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

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

编辑:

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

如果你想逐个属性进行比较,并查看它是否以及在哪里失败,你可以使用下面的列表推导式:

[i for i,j in 
 zip([getattr(obj_1, attr) for attr in dir(obj_1)],
     [getattr(obj_2, attr) for attr in dir(obj_2)]) 
 if not i==j]

这里的额外优势是,当在PyCharm中调试时,您可以压缩一行并在“Evaluate Expression”窗口中输入。

根据具体情况,你可以这样做:

>>> vars(x) == vars(y)
True

参见对象字段中的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来稍微清理它,但当它失败时,您得到的消息是非常没有帮助的。

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

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

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

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