How can I make an existing object read-only?
Eli Stevens (WG.c)
listsub at wickedgrey.com
Mon Oct 4 21:44:31 EDT 2004
Irmen de Jong wrote:
> Alex Martelli wrote:
> (and Steven Bethard also, essentially)
>
>> Instead of passing the bare object, pass it wrapped into something like:
>>
>> class nowrite:
>> def __init__(self, obj): self.__dict__['_obj'] = obj
>> def __getattr__(self, n): return getattr(self._obj, n)
>> def __setattr__(self, n, *args): raise AttributeError, n
>> __delattr__ = __setattr__
>>
>
> Now that was simple, why didn't I think of that myself.
> Too much Java coding apparently clogs up your mind :o)
Quite (I do Java during my day job ;).
Another alternative that actually locks the object down, could look
something like this (of course, all the prints need to get nuked, but
they helped me see what was going on while coding this up):
class Foo(object):
def __init__(self):
# Needed to jumpstart the whole thing
self.__dict__["_CurrentState__setattr__"] = self._readWriteSetattr
self.bar = "bar"
self.baz = "baz"
def ReadWrite(self):
print "ReadWrite"
self._CurrentState__setattr__ = self._readWriteSetattr
def ReadOnly(self):
print "ReadOnly"
self._CurrentState__setattr__ = self._readOnlySetattr
def __setattr__(self, name, value):
self._CurrentState__setattr__(name, value)
def _readWriteSetattr(self, name, value):
print "_readWriteSetattr", name, value
self.__dict__[name] = value
def _readOnlySetattr(self, name, value):
print "_readOnlySetattr", name, value
if name == "_CurrentState__setattr__":
self.__dict__[name] = value
else:
raise AttributeError, "page object is read-only"
While coding this, I learned that:
self.__setattr__ = self._readOnlySetattr
Doesn't DWIM. ;) Hence the _CurrentState__setattr__ hack. Is this
pythonic? Dunno. Thoughts?
I also don't know which would be faster between the proxy and having an
extra level of indirection in __setattr__. I would guess it would
depend on if you do more reads or writes in the tight loops. If your
code is read-heavy, this might actually be a win.
Of course, if you are _really_ concerned with performance, you might
just turn the whole protection thing off when in production.
HTH,
Eli
More information about the Python-list
mailing list