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