I am interested in taking an arbitrary dict and copying it into a new dict, mutating it along the way.
One mutation I would like to do is swap keys and value. Unfortunately, some values are dicts in their own right. However, this generates a "unhashable type: 'dict'" error. I don't really mind just stringifying the value and giving it the key. But, I'd like to be able to do something like this:
for key in olddict:
  if hashable(olddict[key]):
    newdict[olddict[key]] = key
  else
    newdict[str(olddict[key])] = key
Is there a clean way to do this that doesn't involve trapping an exception and parsing the message string for "unhashable type" ?
__hash__() method. You can check for that. A warning about this: In Python 2.5 this will give: {'test': 'dict'}is hashable . It can also give a wrong result in newer versions if a class defines __hash__ to raise a TypeError.
In Python, any immutable object (such as an integer, boolean, string, tuple) is hashable, meaning its value does not change during its lifetime. This allows Python to create a unique hash value to identify it, which can be used by dictionaries to track unique keys and sets to track unique values.
Hashable data types: int , float , str , tuple , and NoneType .
An object is said to be hashable if it has a hash value that remains the same during its lifetime.
Since Python 2.6 you can use the abstract base class collections.Hashable:
>>> import collections
>>> isinstance({}, collections.Hashable)
False
>>> isinstance(0, collections.Hashable)
True
This approach is also mentioned briefly in the documentation for __hash__.
Doing so means that not only will instances of the class raise an appropriate
TypeErrorwhen a program attempts to retrieve their hash value, but they will also be correctly identified as unhashable when checkingisinstance(obj, collections.Hashable)(unlike classes which define their own__hash__()to explicitly raiseTypeError).
def hashable(v):
    """Determine whether `v` can be hashed."""
    try:
        hash(v)
    except TypeError:
        return False
    return True
                        All hashable built in python objects have a .__hash__() method. You can check for that.
olddict = {"a":1, "b":{"test":"dict"}, "c":"string", "d":["list"] }
for key in olddict:
   if(olddict[key].__hash__):
      print str(olddict[key]) + " is hashable"
   else: 
      print str(olddict[key]) + " is NOT hashable"
output
1 is hashable
string is hashable
{'test': 'dict'} is NOT hashable
['list'] is NOT hashable
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With