hashability

James Stroud jstroud at mbi.ucla.edu
Tue Aug 11 20:54:36 EDT 2009


Hello All,

I wrote the function to test hashability of arbitrary objects. My reason 
is that the built-in python (2.5) hashing is too permissive for some 
uses. A symptom of this permissiveness comes from the ability to 
successfully hash() arbitrary objects:

   py> class C(object): pass
   ...
   py> {C():4}[C()]
   ------------------------------------------------------------
   Traceback (most recent call last):
     File "<ipython console>", line 1, in <module>
   <type 'exceptions.KeyError'>: <__main__.C object at 0xe21610>

The basis for the exception is that the two instances do not have the 
same hash() although conceptually they might seem equal to the 
unitiated. Were I to re-design python, I'd throw an exception in this 
case because of the ill-defined behavior one might expect if a C() 
serves as a key for a dict.

To prevent users of one of my libraries from falling into this and 
similar traps (which have potentially problematic consequences), I came 
up with this test for hashability:

def hashable(k):
   try:
     hash(k)
   except TypeError:
     good = False
   else:
     good = (hasattr(k, '__hash__') and
             (hasattr(k, '__eq__') or hasattr(k, '__cmp__')))
   return good

It works as I would like for most of the cases I can invent:

   py> all(map(hashable, [1,1.0,"",(1,2,3)]))
   True
   py> any(map(hashable, [None, [1,2], {}, C(), __import__('sys')]))
   False

Can anyone think of boundary cases I might be missing with this approach?


James



More information about the Python-list mailing list