Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Asking "is hashable" about a Python value

Tags:

python

hash

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" ?

like image 777
Paul Nathan Avatar asked Aug 11 '10 16:08

Paul Nathan


People also ask

How do you check if a value is hashable in Python?

__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.

What is a hashable value in Python?

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.

Which data types are hashable in Python?

Hashable data types: int , float , str , tuple , and NoneType .

What does it mean to be hashable?

An object is said to be hashable if it has a hash value that remains the same during its lifetime.


3 Answers

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 TypeError when a program attempts to retrieve their hash value, but they will also be correctly identified as unhashable when checking isinstance(obj, collections.Hashable) (unlike classes which define their own __hash__() to explicitly raise TypeError).

like image 196
Mark Byers Avatar answered Oct 20 '22 03:10

Mark Byers


def hashable(v):
    """Determine whether `v` can be hashed."""
    try:
        hash(v)
    except TypeError:
        return False
    return True
like image 21
Ned Batchelder Avatar answered Oct 20 '22 02:10

Ned Batchelder


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
like image 5
Chandler Avatar answered Oct 20 '22 01:10

Chandler