Mateen-Hussain
Mateen-Hussain

Reputation: 748

compare two custom lists python

I'm having trouble comparing two list of objects in python

I'm converting a message into

class StatusMessage(object):
    def __init__(self, conversation_id, platform):
        self.__conversation_id = str(conversation_id)
        self.__platform = str(platform)

    @property
    def conversation_id(self):
        return self.__conversation_id

    @property
    def platform(self):
        return self.__platform 

Now when I create two lists of type StatusMessage

>>> expected = []
>>> expected.append(StatusMessage(1, "abc"))
>>> expected.append(StatusMessage(2, "bbc"))

>>> actual = []
>>> actual.append(StatusMessage(1, "abc"))
>>> actual.append(StatusMessage(2, "bbc"))

and then I compare the two lists using

>>> cmp(actual, expected) 

or

>>> len(set(expected_messages_list).difference(actual_list)) == 0

I keep getting failures. When I debug and actually compare for each item within the list like

>>> actual[0].conversation_id == expected[0].conversation_id
>>> actual[0].platform == expected[0].platform

then I always see

True

Doing below returns -1

>>> cmp(actual[0], expected[0])

why is this so. What am I missing???

Upvotes: 3

Views: 1437

Answers (2)

timgeb
timgeb

Reputation: 78690

You must tell python how to check two instances of class StatusMessage for equality.

For example, adding the method

def __eq__(self,other):
    return (self is other) or (self.conversation_id, self.platform) == (other.conversation_id, other.platform)

will have the following effect:

>>> cmp(expected,actual)
0
>>> expected == actual
True

If you want to use cmp with your StatusMessage objects, consider implementing the __lt__ and __gt__ methods as well. I don't know by which rule you want to consider one instance lesser or greater than another instance.

In addition, consider returning False or error-checking for comparing a StatusMessage object with an arbitrary object that has no conversation_id or platform attribute. Otherwise, you will get an AttributeError:

>>> actual[0] == 1
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "a.py", line 16, in __eq__
    return (self is other) or (self.conversation_id, self.platform) == (other.conversation_id, other.platform)
AttributeError: 'int' object has no attribute 'conversation_id'

You can find one reason why the self is other check is a good idea here (possibly unexpected results in multithreaded applications).

Upvotes: 3

William Jackson
William Jackson

Reputation: 1165

Because you are trying to compare two custom objects, you have to define what makes the objects equal or not. You do this by defining the __eq__() method on the StatusMessage class:

class StatusMessage(object):
    def __eq__(self, other):
        return self.conversation_id == other.conversation_id and
               self.platform == other.platform

Upvotes: 0

Related Questions