set using alternative hash function?

Mick Krippendorf mad.mick at gmx.de
Thu Oct 15 09:50:36 EDT 2009


Austin Bingham schrieb:
> I guess we see things differently. I think it's quite natural to want
> a set of unique objects where "unique" is defined as an operation on
> some subset/conflation/etc. of the attributes of the elements. 

What you seem to imply is that the hash function imposes some kind of
uniqueness constraint on the set which uses it. That's just not the
case, the uniqueness constraint is always the (in-)equality of objects,
and for this you can override __eq__. But then you must also ensure that
x.__eq__(y) --> y.__eq__(x) & x.__hash() == y.__hash__().

Diez' solution is the pythonic way, and BTW, mathematically and
pythonically sound, wheras, if the hash function would really impose
uniqueness:

s1 = set(lambda x: hash(x))
s2 = set(lambda x: hash(x.name))

t1 = Buddy(name="jim")
t2 = Buddy(name="joe")
t3 = Buddy(name="joe")

s1.add(t1)
s1.add(t2)
s1.add(t3)

s2.add(t1)
s2.add(t2)
s2.add(t3)

would probaly yield quite strange results:

s3 = s2 | s1 # union. Is s3 == (t1,t2,t3) or is it (t1,t3)?
s4 = s2 - s1 # difference. is s4 == () or do we get an Exception?

In C++/STL the compiler would nag because s1 and s2 are of different
types since the hash function is part of the set's type (AFAIR). With
dynamic typing this isn't possible so you'd have to wait until runtime.

I'd go with Diez' advice and use a dict instead. Or, you could do
something Borg-ish (lookup Borg Pattern) restrained on names, where the
constructor of a class ensures that x.name == y.name --> x == y.

> As far as using a dict, that doesn't really solve my problem. It could
> be part of a solution, I guess, but I would still need functionality
> extrinsic to the dict.

Python isn't strong on encapsulation, so "extrinsic" functionality is
quite common. Nothing to loose sleep over though, because, as Guido
says, "we're all consenting adults here" :-)

Mick.



More information about the Python-list mailing list