简体   繁体   English

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

[英]Most efficient way of comparing the contents of two class instances in python

I'm looking for the most efficient way of comparing the contents of two class instances. 我正在寻找比较两个类实例内容的最有效方法。 I have a list containing these class instances, and before appending to the list I want to determine if their property values are the same. 我有一个包含这些类实例的列表,在追加到列表之前,我想确定它们的属性值是否相同。 This may seem trivial to most, but after perusing these forums I wasn't able specific to what I'm trying to do. 对于大多数人来说,这似乎微不足道,但是仔细阅读了这些论坛之后,我无法明确自己的意图。 Also note that I don't have an programming background. 另请注意,我没有编程背景。

This is what I have so far: 这是我到目前为止的内容:

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))

Before adding to my list, I'd do something like: 在添加到我的列表之前,我会做以下事情:

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

if not found: myList.append(newInstance)

However I'm unclear whether this is the most efficient or python-ic way of comparing the contents of instances of the same class. 但是我不清楚这是比较同一类实例的内容的最有效的方法还是python-ic的方法。

Implement a __eq__ special method instead: 改用__eq__特殊方法

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__

Now you can just use: 现在您可以使用:

if newInstance in myList:

and Python will automatically use the __eq__ special method to test for equality. Python将自动使用__eq__特殊方法测试是否相等。

In my version I retained the ability to pass in a limited set of attributes: 在我的版本中,我保留了传递一组有限的属性的能力:

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

but using all() to make sure we only test as much as is needed. 但是使用all()来确保我们仅测试所需的内容。

Note that we return NotImplemented , a special singleton object to signal that the comparison is not supported; 注意,我们返回NotImplemented ,这是一个特殊的单例对象,以表示不支持比较。 Python will ask the other object if it perhaps supports equality testing instead for that case. 在这种情况下,Python会询问另一个对象是否可能支持相等性测试。

You can implement the comparison magic method __eq__(self, other) for your class, then simply do 您可以为您的类实现比较魔术方法 __eq__(self, other) ,然后只需执行

if instance == newInstance:

As you apparently don't know what attributes your instance will have, you could do: 由于您显然不知道实例将具有哪些属性,因此可以执行以下操作:

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

Your method has one major flaw: if you have reference cycles with classes that both derive from BaseObject , your comparison will never finish and die with a stack overflow. 您的方法有一个主要缺陷:如果您的引用循环都具有从BaseObject派生的类,则您的比较将永远不会结束并且会因堆栈溢出而终止。

In addition, two objects of different classes but with the same attribute values compare as equal. 此外,具有不同属性值的不同类的两个对象比较相等。 Trivial example: any instance of BaseObject with no attributes will compare as equal to any instance of a BaseObject subclass with no attributes (because if issubclass(C, B) and a is an instance of C , then isinstance(a, B) returns True ). 一个简单的例子:没有属性的BaseObject任何实例将与没有属性的BaseObject子类的任何实例进行比较(因为如果issubclass(C, B)aC的实例,则isinstance(a, B)返回True )。

Finally, rather than writing a custom _compare method, just call it __eq__ and reap all the benefits of now being able to use the == operator (including contain testing in lists, container comparisons, etc.). 最后,与其编写自定义_compare方法, _compare直接调用它__eq__并获得现在可以使用==运算符(包括在列表中进行测试,容器比较等)的所有好处。

As a matter of personal preference, though, I'd stay away from that sort-of automatically-generated comparison, and explicitly compare explicit attributes. 不过,出于个人喜好,我会远离那种自动生成的比较,而是显式比较显式属性。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 比较两组的最有效方法是什么? - What is the most efficient way of comparing two sets? 动态创建类实例的最有效方法是什么? - What is the most efficient way to dynamically create class instances? Python可能以MOST有效方法比较两组海量数据 - Python comparing two massive sets of data in the MOST efficient method possible 在python中将文本文件内容转换为字典的最有效方法 - most efficient way to convert text file contents into a dictionary in python 比较python中的类实例 - Comparing class instances in python 在Python中,有没有一种简洁的方法来比较两个文本文件的内容是否相同? - In Python, is there a concise way of comparing whether the contents of two text files are the same? 在python中将两个数字连接到一个数字的最有效方法是什么? - what is the most efficient way of concat two numbers to one number in python? 在 Python 中生成和 zip 两个列表的最干净有效的方法 - Most clean and efficient way to generate and zip two lists in Python 计算 Python 中两组的差异和交集的最有效方法 - Most efficient way to compute differences and intersection of two sets in Python 比较Python中两个几乎相同的CSV的最有效方法? - Most efficient way to compare two near identical CSV's in Python?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM