steve at REMOVE-THIS-cybersource.com.au
Fri Oct 8 19:25:28 CEST 2010
On Fri, 08 Oct 2010 14:00:17 +0000, kj wrote:
> In <i8loa2$3oe$1 at reader1.panix.com> kj <no.email at 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:
>> 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 inner(self, *args, **kwargs):
cn = self.__class__.__name__
raise TypeError('%s instance is not mutable' % cn)
inner.__name__ = name
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:
for name in 'update clear'.split() # and the others
setattr(FrozenDict, name, no_mutate_factory(name))
del name # Avoid namespace pollution, if you care.
More information about the Python-list