[英]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)
且a
是C
的实例,则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.