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
--
http://mail.python.org/mailman/listinfo/python-list

Reply via email to