On Fri, 08 Oct 2010 14:00:17 +0000, kj wrote: > In <i8loa2$3o...@reader1.panix.com> kj <no.em...@please.post> writes: > >>At any rate, using your [i.e. Arnaud's] suggestions in this and your >>other post, the current implementation of frozendict stands at: > >>class frozendict(dict): >> for method in ('__delitem__ __setitem__ clear pop popitem' >> 'setdefault update').split(): >> exec """ >>def %s(self, *a, **k): >> cn = self.__class__.__name__ >> raise TypeError("'%%s' object is not mutable" %% cn) >>""" % method > >> def __hash__(self): >> return hash(frozenset(self.items())) > >>...which is a lot nicer! > > As a side comment on my own post, this is the second time in less than a > week that I find myself having to resort to exec'ing some code generated > from a template. This one is worse, because there's nothing > runtime-dependent about the code being exec'd.
Er, *all* Python classes are created at runtime. The class statement is executed at runtime, not compile time. Not that it really matters. But in any case, it's easy enough to avoid exec with a factory function. The following is untested, but should work: def no_mutate_factory(name): def inner(self, *args, **kwargs): cn = self.__class__.__name__ raise TypeError('%s instance is not mutable' % cn) inner.__name__ = name return inner class FrozenDict(dict): update = no_mutate_factory('update') clear = no_mutate_factory('clear') # ... It's a bit messy to have to list the name of the method twice. But you can inject the appropriate methods into the class by adding them from outside the class block: class FrozenDict(dict): pass for name in 'update clear'.split() # and the others setattr(FrozenDict, name, no_mutate_factory(name)) del name # Avoid namespace pollution, if you care. -- Steven -- http://mail.python.org/mailman/listinfo/python-list