Consider this code:
a = {...} # a is an dict with arbitrary contents
b = a.copy()
There isn't actually any such thing as mutability or immutability at the language level in Python. Some objects provide no way to change them (eg. strings and tuples), and so are effectively immutable, but it's purely conceptual; there's no property at the language level indicating this, neither to your code nor to Python itself.
Immutability is not actually relevant to dicts; it's perfectly fine to use mutable values as keys. What matters is comparison and hashing: the object must always remain equal to itself. For example:
class example(object):
def __init__(self, a):
self.value = a
def __eq__(self, rhs):
return self.value == rhs.value
def __hash__(self):
return hash(self.value)
a = example(1)
d = {a: "first"}
a.data = 2
print d[example(1)]
Here, example
is not immutable; we're modifying it with a.data = 2
. Yet, we're using it as a key of a hash without any trouble. Why? The property we're changing has no effect on equality: the hash is unchanged, and example(1)
is always equal to example(1)
, ignoring any other properties.
The most common use of this is caching and memoization: having a property cached or not doesn't logically change the object, and usually has no effect on equality.
(I'm going to stop here--please don't ask five questions at once.)