Set and {} comparison confusion

Roman Yakovenko roman.yakovenko at actimize.com
Thu Sep 9 09:49:25 CEST 2004


Thanks. I have an other question, more general:

I have class A that defines __eq__ and __ne__.
I have 2 lists of instances of A

What is the right way to find out whether those lists
are equal (as sets) or not? 

Thanks for help



> -----Original Message-----
> From: Alex Martelli [mailto:aleaxit at yahoo.com]
> Sent: Thursday, September 09, 2004 10:29 AM
> To: python-list at python.org
> Subject: Re: Set and {} comparison confusion
> 
> 
> Roman Yakovenko <roman.yakovenko at actimize.com> wrote:
> 
> > Hi. Could somebody explain why sets and dict are different ?
> 
> sets.Set is build around dict, so let's concentrate on dict, the set
> just follows from there.
> 
> > 
> > from sets import Set as set
> > 
> > class A(object):
> >       def __init__( self, x ):
> >               self.x = x
> >       def __eq__( self, other ):
> >               return self.__dict__ == other.__dict__
> 
> This class is NOT correctly hashable.
> 
> A crucial semantic condition for hashing is:
> 
>     X==Y   ***MUST imply***   hash(X)==hash(Y)
> 
> But this is not ensured by this class A.  For example, as 
> you've noticed
> all A(1) instances compare equal to each other:
> 
> > print 'A(1) == A(1)', A(1) == A(1)
> 
> and yet their hashes are all different (and happen to equal 
> their id's,
> since you have not overridden __hash__):
> 
> xx = []
> for i in xrange(4):
>     xx.append(A(1))
>     print hash(xx[-1])
> 
> emits, e.g.:
> 
> 255856
> 256752
> 359376
> 357840
> 
> ((note we're careful to keep the A(1)'s around, otherwise, if one had
> been garbage collected the next one might happen to be 
> allocated just at
> the same place, thus accidentally have the same id...)).
> 
> As you are violating a semantic precondition of dict (that it be only
> keyed into by _validly_ hashable keys), don't be surprised if the
> behavior of such dicts is weird.  You can imagine equality comparison
> starts by checking equality of hash values for keys to bail 
> out fast in
> most cases, here the hash values are different, so, poof.
> 
> Not easy to make that class A _correctly_ hashable, either (and it
> really should be immutable too).  Assuming self.x is always 
> hashable and
> nobody ever reassigns it nor assigns any other attribute, you 
> could try
> adding something like...:
> 
>     def __hash__(self):
>         return hash(tuple(self.__dict__.iteritems()))
> 
> 
> Alex
> -- 
> http://mail.python.org/mailman/listinfo/python-list
> 



More information about the Python-list mailing list