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


当前回答

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

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

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

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

其他回答

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

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

我写了这个,并把它放在我的项目中的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来稍微清理它,但当它失败时,您得到的消息是非常没有帮助的。

下面通过在两个对象层次结构之间进行深度比较来工作(在我有限的测试中)。In处理各种情况,包括对象本身或其属性是字典的情况。

def deep_comp(o1:Any, o2:Any)->bool:
    # NOTE: dict don't have __dict__
    o1d = getattr(o1, '__dict__', None)
    o2d = getattr(o2, '__dict__', None)

    # if both are objects
    if o1d is not None and o2d is not None:
        # we will compare their dictionaries
        o1, o2 = o1.__dict__, o2.__dict__

    if o1 is not None and o2 is not None:
        # if both are dictionaries, we will compare each key
        if isinstance(o1, dict) and isinstance(o2, dict):
            for k in set().union(o1.keys() ,o2.keys()):
                if k in o1 and k in o2:
                    if not deep_comp(o1[k], o2[k]):
                        return False
                else:
                    return False # some key missing
            return True
    # mismatched object types or both are scalers, or one or both None
    return o1 == o2

这是一个非常棘手的代码,所以请在注释中添加任何可能不适合你的情况。

在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

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

[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”窗口中输入。