比较python中两个类实例的内容的最有效方法

时间:2013-12-10 15:29:27

标签: python object instance

我正在寻找比较两个类实例内容的最有效方法。我有一个包含这些类实例的列表,在附加到列表之前,我想确定它们的属性值是否相同。这对大多数人来说似乎微不足道,但在仔细阅读这些论坛后,我无法具体到我想要做的事情。另请注意,我没有编程背景。

这是我到目前为止所做的:

class BaseObject(object):
    def __init__(self, name=''):
        self._name = name


    def __repr__(self):
        return '<{0}: \'{1}\'>'.format(self.__class__.__name__, self.name)

    def _compare(self, other, *attributes):
        count = 0
        if isinstance(other, self.__class__):
            if len(attributes):
                for attrib in attributes:
                    if (attrib in self.__dict__.keys()) and (attrib in other.__dict__.keys()):
                        if self.__dict__[attrib] == other.__dict__[attrib]:
                            count += 1
                return (count == len(attributes))
            else:
                for attrib in self.__dict__.keys():
                    if (attrib in self.__dict__.keys()) and (attrib in other.__dict__.keys()):
                        if self.__dict__[attrib] == other.__dict__[attrib]:
                            count += 1
                return (count == len(self.__dict__.keys()))
    def _copy(self):
        return (copy.deepcopy(self))

在添加到我的列表之前,我会执行以下操作:

found = False
for instance in myList:
    if instance._compare(newInstance): 
        found = True
        Break

if not found: myList.append(newInstance)

但是我不清楚这是否是比较同一类实例内容的最有效或python-ic方式。

3 个答案:

答案 0 :(得分:6)

实施__eq__ special method代替:

def __eq__(self, other, *attributes):
    if not isinstance(other, type(self)):
        return NotImplemented

    if attributes:
        d = float('NaN')  # default that won't compare equal, even with itself
        return all(self.__dict__.get(a, d) == other.__dict__.get(a, d) for a in attributes)

    return self.__dict__ == other.__dict__

现在你可以使用:

if newInstance in myList:

并且Python将自动使用__eq__特殊方法来测试相等性。

在我的版本中,我保留了传递一组有限属性的能力:

instance1.__eq__(instance2, 'attribute1', 'attribute2')

但使用all()确保我们只测试所需的数量。

请注意,我们返回NotImplemented,一个特殊的单例对象,表示不支持比较; Python会询问其他对象,如果它可能支持相等测试而不是那种情况。

答案 1 :(得分:5)

您可以为您的班级实施comparison magic method __eq__(self, other),然后执行

if instance == newInstance:

由于您显然不知道您的实例将具有哪些属性,您可以执行以下操作:

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

答案 2 :(得分:0)

你的方法有一个主要的缺陷:如果你的引用周期都是来自BaseObject的类,你的比较将永远不会完成并因堆栈溢出而死亡。

此外,两个不同类但具有相同属性值的对象相等。简单示例:任何没有属性的BaseObject实例都将与没有属性的BaseObject子类的任何实例相等(因为如果issubclass(C, B)a是一个实例C,然后isinstance(a, B)返回True)。

最后,不要编写自定义_compare方法,只需将其称为__eq__,并获得现在能够使用==运算符的所有好处(包括在列表中包含测试,容器比较等。)。

但是,作为个人偏好的问题,我会远离那种自动生成的比较,并明确比较显式属性。