How can I make an existing object read-only?

Steven Bethard steven.bethard at gmail.com
Mon Oct 4 17:22:48 EDT 2004


Irmen de Jong <irmen <at> -nospam-remove-this-xs4all.nl> writes:
> Say I have an object that's initialized with a bunch of attributes.
> I want to pass the object to a piece of code that is not allowed
> to add/delete/set attributes on this object.
> When control returns, the code is again allowed to make changes
> to the object.

Would a proxy object work for you?  I'm thinking something along the lines of:
    http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/252151

Start with a class like:

class Proxy(object):
    def __init__(self, obj):
        super(Proxy, self).__init__(obj)
        self.__dict__['_obj'] = obj
    def __getattr__(self, attr):
        return getattr(self._obj, attr)
    def __setattr__(self, attr, val):
        raise AttributeError, "object is read-only" 

Then you can get the following behavior:

>>> class S(object):
... 	def __init__(self, x):
... 		self.x = x
... 
>>> s = S(1)
>>> s.x
1
>>> s.x = 2
>>> s.x
2
>>> p = Proxy(s)
>>> p.x
2
>>> p.x = 3
Traceback (most recent call last):
  File "<interactive input>", line 1, in ?
  File "D:\Steve\My Programming\python\temp.py", line 8, in __setattr__
    self._obj = obj
AttributeError: object is read-only
>>> s.x = 1
>>> p.x
1

Basically the idea here is that you don't actually pass your object to the 
other piece of code; you pass a wrapper object that acts like your object.  
This means that you only get the __setattr__ overhead in the other code, but 
you do also get the overhead of the additional lookup (proxy._obj instead of 
just _obj).

I don't know if these are acceptable costs to you, but it is, at least, an 
alternative, I think.

Steve




More information about the Python-list mailing list