You might also look at the discussion at http://code.google.com/p/sympy/issues/detail?id=135. We used to override __eq__ to retune Eq(), but we changed it to be like it is now. You can see at around comment 22 that the main reason for the change was for performance purposes.
But I would argue for it just in terms of functionality. Exact comparison is used 100 more often than Eq(), so the nice syntax should go to that. Also, it's more Pythonic (it's how everything else works). And as Robert pointed out, it is necessary for hashing to work correctly in some cases to make __eq__ implement equality. Aaron Meurer On May 25, 2011, at 9:30 PM, Robert Kern wrote: > On Wed, May 25, 2011 at 19:32, Matthew <mrock...@gmail.com> wrote: >> Is the only issue with overloading __eq__ that hashing goes away (thus >> not allowing use of SymPy objects inside dicts/sets, etc...)? > > No. Having the ability to ask if two sympy expressions are > structurally the same is important in some manipulations of those > structures. > >> Apparently numpy gets around this by defining a __hash__ method. > > No, it doesn't. First, numpy arrays are mutable and so cannot be > hashed; we don't get around anything. Second, in order to be hashable, > you must also define an __eq__() such that if (x==y) then > (hash(x)==hash(y)). dicts and sets use an equality comparison when two > objects fall into the same hash bucket to actually determine whether > the object is in the dict/set. The __hash__ is just an optimization, > not the whole of the operation. This is actually why the mutability of > arrays forbids them from being dict keys: if the array changes its > values after it has been hashed and assigned a hash bucket in the > dict, then later comparisons will be incorrect. > >> Could >> we do the same? Are there other concerns with overloading __eq__? >> >> Consider the following example. >> >>>>> class foo: >> ... def __init__(self, a, b): >> ... self.a, self.b = a, b >> ... def __eq__(self, other): >> ... return other >> ... def __hash__(self): >> ... return hash((self.a, self.b)) >>>>> f = foo(1,2) >>>>> f == 5 >> 5 >>>>> set((f, 5)) >> set([<__main__.foo instance at 0x9866bcc>, 5]) > > Yes, it believed you that it could hash the foo object and faithfully > put it into the right bucket given the hash code you calculated. > However, you will run into problems actually *using* the set, checking > for containment, and adding and removing items. > > [~] > |1> class foo(object): > ..> def __init__(self, a, b): > ..> self.a = a > ..> self.b = b > ..> def __eq__(self, other): > ..> return other > ..> def __hash__(self): > ..> return hash((self.a, self.b)) > ..> > > [~] > |2> f = foo(1,2) > > [~] > |3> s = set([f, 5]) > > [~] > |4> s > set([<__main__.foo at 0x4e9fed0>, 5]) > > [~] > |5> (1,2) in s > True > > > This happens because hash((1,2)) == hash(f), so the set looks in f's > bucket for items that actually equal the test object. So it runs > f.__eq__((1,2)), gets back (1,2), passes it to bool() to interpret it > as a real boolean, gets True, so it thinks (1,2) is an object that is > already in there. > > -- > Robert Kern > > "I have come to believe that the whole world is an enigma, a harmless > enigma that is made terrible by our own mad attempt to interpret it as > though it had an underlying truth." > -- Umberto Eco > > -- > You received this message because you are subscribed to the Google Groups > "sympy" group. > To post to this group, send email to sympy@googlegroups.com. > To unsubscribe from this group, send email to > sympy+unsubscr...@googlegroups.com. > For more options, visit this group at > http://groups.google.com/group/sympy?hl=en. > -- You received this message because you are subscribed to the Google Groups "sympy" group. To post to this group, send email to sympy@googlegroups.com. To unsubscribe from this group, send email to sympy+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/sympy?hl=en.