views:

169

answers:

2

For example, suppose I do this:

>>> class foo(object):
...     pass
... 
>>> class bar(foo):
...     pass
... 
>>> some_dict = { foo : 'foo',
... bar : 'bar'}
>>> 
>>> some_dict[bar]
'bar'
>>> some_dict[foo]
'foo'
>>> hash(bar)
165007700
>>> id(bar)
165007700

Based on that, it looks like the class is getting hashed as its id number. Therefore, there shouldn't be any danger of worrying about, say, a bar hashing as either a foo or a bar or hash values changing if I mutate the class.

Is this behavior reliable, or are there any gotchas here?

+4  A: 

Yes, any object that doesn't implement a __hash__() function will return its id when hashed. From Python Language Reference: Data Model - Basic Customization:

User-defined classes have __cmp__() and __hash__() methods by default; with them, all objects compare unequal (except with themselves) and x.__hash__() returns id(x).

However, if you're looking to have a unique identifier, use id to be clear about your intent. A hash of an object should be a combination of the hashes of its components. See the above link for more details.

Andrew Keeton
Any class whose *metaclass* doesn't have a __hash__() function.
Ants Aasma
It should be noted that although this is in the "what's new for Python 2.6" page, this behavior seems to work for me under python 2.4.
Jason Baker
@Jason I changed the reference to the general documentation.
Andrew Keeton
One thing that someone from work added: it's important never to persist a dictionary that uses id in this manner. The id is the memory address of the object, and it is only valid for the current process.
Jason Baker
+4  A: 

Classes have default implementations of __eq__ and __hash__ that use id() to make comparisons and compute hash values, respectively. That is, they compare by identity. The primary rule for implementing __hash__ methods is that if two objects compare equal to each other, they must also have the same hash value. Hash values can be seen as just an optimization used by dicts and sets to do find equal objects faster. Consequently, if you change __eq__ to do a different kind of equality testing, you must also change your __hash__ implementation to agree with that choice.

Classes that use identity for comparisons can be freely mutated and used in dicts and sets because their identity never changes. Classes that implement __eq__ to compare by value and allow mutation of their values cannot be used in hash collections.

Robert Kern