Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

objects as keys in python dictionaries

I'm trying to use an object as a key in a python dictionary, but it's behaving in a way that I can't quite understand.

First I create a dictionary with my object as the key:

package_disseminators = {   ContentType("application", "zip", "http://other/property") : "one",   ContentType("application", "zip") : "two" } 

Now create another object that is "the same" as one which is a key.

content_type = ContentType("application", "zip", "http://other/property") 

I have given the ContentType object custom __eq__ and custom __str__ methods, such that the __eq__ method compares the __str__ values.

Now, some interactive python:

>>> for key in package_disseminators: ...     if key == content_type: ...             print "match" ...     else: ...             print "no match" ...  no match match  >>> content_type in package_disseminators.keys() True 

Ok, so it looks like my object is definitely being identified properly as a key, so:

>>> package_disseminators[content_type] Traceback (most recent call last):   File "<stdin>", line 1, in <module> KeyError: (& (type="application/zip") (packaging="http://other/property") ) 

Er ... ok? So content_type is in the package_disseminators.keys() list, but isn't a key?

>>> package_disseminators.has_key(content_type) False 

Apparently not.

I presume that the comparison process that Python uses to determin equality differs between a straight "in" statement on a list and actually looking up a key in a dict, but I don't know how. Any tips or insights?

like image 702
Richard J Avatar asked Feb 09 '11 20:02

Richard J


People also ask

Can objects be keys in Python dictionary?

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 Python dictionary values be objects?

Takeaway: A dictionary key must be an immutable object. A dictionary value can be any object.

Are objects in Python dictionaries?

All objects in Python have an attribute __dict__, which is a dictionary object containing all attributes defined for that object itself. The mapping of attributes with its values is done to generate a dictionary.

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

only immutable type of objects like string, tuple or integer etc. can be used as keys in the dictionaries.


1 Answers

From the python documentation:

A dictionary’s keys are almost arbitrary values. Values that are not hashable, that is, values containing lists, dictionaries or other mutable types (that are compared by value rather than by object identity) may not be used as keys.

Hashable is defined as follows

An object is hashable if it has a hash value which never changes during its lifetime (it needs a __hash__() method), and can be compared to other objects (it needs an __eq__() or __cmp__() method). Hashable objects which compare equal must have the same hash value.

Hashability makes an object usable as a dictionary key and a set member, because these data structures use the hash value internally.

So if you want to do this, you need to override the default __hash__() method on your object (see the comment from Steven Rumbalski below for further explanation).


>>> content_type in package_disseminators.keys() True 

I suppose this works because dict.keys() returns a list, and __contains__ probably checks for equality, but not for the same hashes.

like image 90
Reiner Gerecke Avatar answered Sep 19 '22 10:09

Reiner Gerecke