Immutable dictionary, only use as a key for another dictionary
<p>I had the need to implement a hashable dict so I could use a dictionary as a key for another dictionary.</p>

<p>A few months ago I used this implementation: <a href="http://stackoverflow.com/questions/1151658/python-hashable-dicts">Python hashable dicts</a></p>

<p>However I got a notice from a colleague saying 'it is not really immutable, thus it is not safe. You can use it, but it does make me feel like a sad Panda'.</p>

<p>So I started looking around to create one that is immutable. I have no need to compare the 'key-dict' to another 'key-dict'. Its only use is as a key for another dictionary.</p>

<p>I have come up with the following:</p>

<pre><code>class HashableDict(dict):
    """Hashable dict that can be used as a key in other dictionaries"""

    def __new__(self, *args, **kwargs):
        # create a new local dict, that will be used by the HashableDictBase closure class
        immutableDict = dict(*args, **kwargs)

        class HashableDictBase(object):
            """Hashable dict that can be used as a key in other dictionaries. This is now immutable"""

            def __key(self):
                """Return a tuple of the current keys"""
                return tuple((k, immutableDict[k]) for k in sorted(immutableDict))

            def __hash__(self):
                """Return a hash of __key"""
                return hash(self.__key())

            def __eq__(self, other):
                """Compare two __keys"""
                return self.__key() == other.__key() # pylint: disable-msg=W0212

            def __repr__(self):
                """@see: dict.__repr__"""
                return immutableDict.__repr__()

            def __str__(self):
                """@see: dict.__str__"""
                return immutableDict.__str__()

            def __setattr__(self, *args):
                raise TypeError("can't modify immutable instance")
            __delattr__ = __setattr__

        return HashableDictBase()
</code></pre>

<p>I used the following to test the functionality:</p>

<pre><code>d = {"a" : 1}

a = HashableDict(d)
b = HashableDict({"b" : 2})

print a
d["b"] = 2
print a

c = HashableDict({"a" : 1})

test = {a : "value with a dict as key (key a)",
        b : "value with a dict as key (key b)"}

print test[a]
print test[b]
print test[c]
</code></pre>

<p>which gives:</p>

<blockquote>
  <p>{'a': 1}<br>
  {'a': 1}<br>
  value with a dict as key (key a)<br>
  value with a dict as key (key b)<br>
  value with a dict as key (key a)  </p>
</blockquote>

<p>as output  </p>

<p>Is this the 'best possible' immutable dictionary that I can use that satisfies my requirements? If not, what would be a better solution?</p>
