3

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

William Jackson
  • 1,130
  • 10
  • 24
Mateen-Hussain
  • 718
  • 1
  • 13
  • 29

2 Answers2

3

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

Community
  • 1
  • 1
timgeb
  • 76,762
  • 20
  • 123
  • 145
  • Thanks timgeb for your answer. But this is the thing, when I compare the order of the elements in the list shouldnt matter. This is why my first approach was to use set and difference – Mateen-Hussain Feb 02 '16 at 09:57
  • Well I tried sorting the list and then did the comparision and it worked for me. – Mateen-Hussain Feb 02 '16 at 09:59
0

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
William Jackson
  • 1,130
  • 10
  • 24