Can any immutable data type be used as a python dictionary key?
<p>So I've gone through a few books and sites. Most of the listed possible data types are immutable. I understand how mutable data types can cause problems.</p>

<p>Also tuples were mentioned as possible keys, but when you make the tuples elements lists it raises an error. So I thought that any key, as long as it's immutable is acceptable for a dictionary. Is this correct?</p>

<p>Any object, as long as it is <a href="https://docs.python.org/2/glossary.html#term-hashable"><strong>hashable</strong></a>, can be used as a key:</p>

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

<p>Immutability makes it possible to produce a stable hash, but a mutable custom class is fine as long as you don't mutate the state that is used to produce the hash. </p>

<p>Tuples are only hashable if they only contain hashable objects; the hash of a tuple is determined by the hashes of the contents, as that's also what determines if two tuples are equal. You can't hash a tuple containing a list, for example:</p>

<pre><code>&gt;&gt;&gt; l = ['foo', 'bar']
&gt;&gt;&gt; t = (42, l)  # contains a list
&gt;&gt;&gt; hash(t)
Traceback (most recent call last):
  File "&lt;stdin&gt;", line 1, in &lt;module&gt;
TypeError: unhashable type: 'list'
</code></pre>

<p>A list is not hashable, because it too would have to build a hash from the contents (as it uses the contents to determine if two lists are equal), but that hash would change over the list's lifetime as you can easily mutate what is in the list.</p>

<p>A custom class can be used as a key provided that the hash is based on the same variables that make two objects equal. The default implementation for custom classes is to only have two instances be equal if they are the <em>exact same instance</em>, making them hashable by default. But the following class is also hashable, because the data that changes is <em>not</em> used to determine equality:</p>

<pre><code>class HashableDemo(object):
    def __init__(self, value):
        self._value = value
        self._count = 0

    def increment(self):
        self._count += 1

    def __eq__(self, other):
        if not isinstance(other, HashableDemo):
            return False
        return self._value == other._value

    def __hash__(self):
        return hash(self._value)
</code></pre>

<p>The class mutates <code>_count</code> but that attribute is not used to determine equality, leaving the hash stable.</p>

python python-2.7 dictionary