Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using object as key in dictionary in Python - Hash function

I am trying to use an object as the key value to a dictionary in Python. I follow the recommendations from some other posts that we need to implement 2 functions: __hash__ and __eq__

And with that, I am expecting the following to work but it didn't.

class Test:
    def __init__(self, name):
        self.name = name
        
    def __hash__(self):
        return hash(str(self.name))
        
    def __eq__(self, other):
        return str(self.name) == str(other,name)
        
        
def TestMethod():
    test_Dict = {}
    
    obj = Test('abc')
    test_Dict[obj] = obj
    
    print "%s" %(test_Dict[hash(str('abc'))].name)       # expecting this to print "abc" 

But it is giving me a key error message:

KeyError: 1453079729188098211
like image 662
Ken Ly Avatar asked Jul 03 '13 08:07

Ken Ly


People also ask

Can you use an object as a key in a dictionary Python?

Dictionaries in PythonAlmost any type of value can be used as a dictionary key in Python. You can even use built-in objects like types and functions.

Can we use an object as a key for a Hashmap in Python?

@Skurmedel: Yes, but although you can call cmp and use = on user classes which do not override these methods, one of them must be implemented to meet the questioner's requirement that instances with similar name and location have the same dictionary key.

What type of objects can be used as keys in dictionaries in Python?

We can use integer, string, tuples as dictionary keys but cannot use list as a key of it .

Can you hash objects in Python?

Python hash() function is a built-in function and returns the hash value of an object if it has one. The hash value is an integer which is used to quickly compare dictionary keys while looking at a dictionary.


2 Answers

You don't need to redefine hash and eq to use an object as dictionary key.

class Test:
    def __init__(self, name):
        self.name = name

test_Dict = {}

obj = Test('abc')
test_Dict[obj] = obj

print test_Dict[obj].name

This works fine and print abc. As explained by Ignacio Vazquez-Abrams you don't use the hash of the object but the object itself as key to access the dictionary value.


The examples you found like python: my classes as dict keys. how? or Object of custom type as dictionary key redefine hash and eq for specific purpose.

For example consider these two objects obj = Test('abc') and obj2 = Test('abc').

test_Dict[obj] = obj
print test_Dict[obj2].name

This will throw a KeyError exception because obj and obj2 are not the same object.

class Test:
    def __init__(self, name):
        self.name = name

    def __hash__(self):
        return hash(str(self.name))

    def __eq__(self, other):
        return str(self.name) == str(other.name)

obj = Test('abc')
obj2 = Test('abc')       

test_Dict[obj] = obj
print test_Dict[obj2].name

This print abc. obj and obj2 are still different objects but now they have the same hash and are evaluated as equals when compared.

like image 86
Pierre Avatar answered Oct 24 '22 20:10

Pierre


Elements of a mapping are not accessed by their hash, even though their hash is used to place them within the mapping. You must use the same value when indexing both for storage and for retrieval.

like image 38
Ignacio Vazquez-Abrams Avatar answered Oct 24 '22 19:10

Ignacio Vazquez-Abrams