import copy class frozendict(dict): def _blocked_attribute(obj): raise AttributeError, "A frozendict cannot be modified." _blocked_attribute = property(_blocked_attribute) __delitem__ = __setitem__ = clear = _blocked_attribute pop = popitem = setdefault = update = _blocked_attribute def __new__(cls, *args, **kw): new = dict.__new__(cls) args_ = [] for arg in args: if isinstance(arg, dict): arg = copy.copy(arg) for k, v in arg.items(): if isinstance(v, dict): arg[k] = frozendict(v) elif isinstance(v, list): v_ = list() for elm in v: if isinstance(elm, dict): v_.append( frozendict(elm) ) else: v_.append( elm ) arg[k] = tuple(v_) args_.append( arg ) else: args_.append( arg ) dict.__init__(new, *args_, **kw) return new def __init__(self, *args, **kw): pass def __hash__(self): try: return self._cached_hash except AttributeError: h = self._cached_hash = hash(tuple(sorted(self.items()))) return h def __repr__(self): return "frozendict(%s)" % dict.__repr__(self)