views:

192

answers:

3

I'm working on a collection class that I want to create an __eq__ method for. It's turning out to be more nuanced than I thought it would be and I've noticed several intricacies as far as how the built-in collection classes work.

What would really help me the most is a good example. Are there any pure Python implementations of an __eq__ method either in the standard library or in any third-party libraries?

+4  A: 

Parts are hard. Parts should be simple delegation.

def __eq__( self, other ):
   if len(self) != len(other):
       # Can we continue?  If so, what rule applies?  Pad shorter?  Truncate longer?
   else:
       return all( self[i] == other[i] for i in range(len(self)) )
S.Lott
I tried that, but there are a couple of nuances here though. For instance, the following compares False: `(1,2,3) == [1,2,3]`. That's why I was wanting an example: to make sure I know about all of the corner cases and whatnot.
Jason Baker
(1,2,3) is not equal to [1,2,3] because they're different types. What type coercion rules do you think should apply? That's quite complex. That's the "more general" type? `tuple(self[i]) == tuple(other[i])`
S.Lott
Not all collections are indexable - such as sets - and there is no guarantee that equal collections would have their items in the same order.
Paul McGuire
@S.Lott - you're correct. The answer as written, however, would make a tuple and a list compare as equal as it does not check for type.
Jason Baker
@Paul McGuire: I'm not sure how you can compare a set with a tuple or a list. It doesn't even make sense to me. You'll have to provide a more detailed explanation of what that could possibly mean.
S.Lott
@Jason Baker: Checking for type should never be necessary at the collection level. That's (generally) the problem of the individual elements. If this "collection equality" imposes method requirements on the individual elements, you've really pushed the envelop on what "equality" might mean. You'd need to provide all of your specific rules in your question.
S.Lott
+1, very elegant
orip
@S.Lott - I just want a well-behaved data structure that does what you'd expect. As you note, checking the type at the collection level probably isn't the best idea (and I agree). But as you also note, (1,2,3) != [1,2,3] because they're different types, and I feel it's better to be wrong and consistent than correct and inconsistent. I can't provide a set of rules (beyond what's in the question already) because I don't know what the rules are. That's why I asked the question. :-)
Jason Baker
@Jason Baker: The rules for comparison are "whatever makes you happy". The built-in rules appear to be unsatisfactory. Therefore, you must define the rules you think should apply. This is -- generally -- not a nuanced problem because the rules are already built in. For some reason, you want different rules. You have to specify -- precisely -- what those rules are. If you're going to have a lot of cases, you might want to rethink why you're doing this.
S.Lott
A: 

Make sure you write lots of unit tests

You don't really specify in the question how lists and tuples should compare

if you can give a bunch of testcases with True/False it would help

gnibbler
+1  A: 

Take a look at "collections.py". The latest version (from version control) implements an OrderedDict with an __eq__. There's also an __eq__ in sets.py

Andrew Dalke
Thank you. I thought that collections was implemented in C...
Jason Baker
In Python 2.5 and 2.6 it is a C extension module. In 2.7 (from version control) it's a Python module which imports deque and defaultdiect from the C extension module _collections. The OrderedDict is new in 3.1 and backported to 2.7.
Andrew Dalke