How can I make an existing object read-only?

Alex Martelli aleaxit at
Tue Oct 5 08:13:19 CEST 2004

Eli Stevens (WG.c) <listsub at> wrote:
>      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)
>          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.

...or implement it by changing the object's *class*...:

class RO_class(TrueClass):
    def makeReadWrite(self): self.__class__ = TrueClass
    def __setattr__(self, n, v=''): raise AttributeError, n
    __delattr__ = __setattr__

def makeReadOnly(obj): obj.__class__ = RO_class

This is a very Pythonic approach to dealing with an object that exists
in two 'states', each rather persistent and with different behavior; it
is better performing and neater than using an obj._state and having 'if
self._state: ... else: ...' statements strewn around.

Your approach (switching boundmethods instead of a passive state flag or
the class itself) is somewhere in-between -- it may require indirection
when special methods are involved (since, in the new object model,
Python looks special methods up per-class, not per-instance), it may
require switching more than one method (more flexible if needed, but
otherwise boilerplatey if you always switch methods as a group).

As I recall, the early prototypes for the new object model (pre-release
2.2's) had obj.__class__ as read-only; it was changed to read/write
specifically to enable this idiom -- a fact which appears to me to
support the contention that this IS a highly Pythonic approach, not just
a hack which accidentally happens to work...


More information about the Python-list mailing list