best practices for making read-only attributes of an object

T

Tim Chase

I've set up an object and would like to make certain
attributes read-only (or at least enforce it without doing
extra work, as per name-mangling or the like). Ideally, the
property would be set in the __init__, and then not be
allowed to change.

The best solution I've been able to come up with is
something of the form:


class Foo:
def __init__(self, name, value):
self.__dict__['_name'] = name
self.value = value
def __getattr__(self, attr):
name = "_%s" % attr
if name in self.__dict__: return self.__dict__[name]
raise AttributeError, attr
def __setattr__(self, attr, value):
if attr == 'value':
self.__dict__['value'] = value
else:
raise AttributeError, attr

Is there a better ("more pythonic") way to do this?
Particularly if it plays well with sub-classing Foo.

Thanks,

-tim
 
B

bruno at modulix

Tim said:
I've set up an object and would like to make certain attributes
read-only (or at least enforce it without doing extra work, as per
name-mangling or the like). Ideally, the property would be set in the
__init__, and then not be allowed to change.

The best solution I've been able to come up with is something of the form:


class Foo:
old-style classes are deprecated, please use new-style classes:
class Foo(object):
def __init__(self, name, value):
self.__dict__['_name'] = name
self.value = value
def __getattr__(self, attr):
name = "_%s" % attr
if name in self.__dict__: return self.__dict__[name]
raise AttributeError, attr
def __setattr__(self, attr, value):
if attr == 'value':
self.__dict__['value'] = value
else:
raise AttributeError, attr

Is there a better ("more pythonic") way to do this?

One usually uses properties withour setter:

class Parrot(object):
def __init__(self, is_dead):
self._is_dead = is_dead

is_dead = property(fget=lambda self: self._is_dead)

p = Parrot(False)
print p, p.is_dead
Particularly if it
plays well with sub-classing Foo.

class DeadBlueParrot(Parrot):
def __init__(self):
self._color = "Blue"
Parrot.__init__(self, True)

color = property(fget=lambda self: self._color)

d = DeadBlueParrot()
print d, d.color, d.is_dead

HTH
 
J

James Stroud

bruno said:
old-style classes are deprecated, please use new-style classes:
class Foo(object):

This should be re-phrased to 'Use new-style classes, or else!'

py> class Foo:
.... def __init__(self, color):
.... self._color = color
.... color = property(fget=lambda self: self._color)
....
py> p = Foo('red')
py> p.color
'red'
py> p.color = 'green' # shouldn't be able to do this
py> p.color
'green'
py>
py> class Parrot(object):
.... def __init__(self, color):
.... self._color = color
.... color = property(fget=lambda self: self._color)
....
py> p = Parrot('orange')
py> p.color
'orange'
py> p.color = 'pink'
Traceback (most recent call last):
File "<stdin>", line 1, in ?
AttributeError: can't set attribute

James

--
James Stroud
UCLA-DOE Institute for Genomics and Proteomics
Box 951570
Los Angeles, CA 90095

http://www.jamesstroud.com/
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,767
Messages
2,569,572
Members
45,046
Latest member
Gavizuho

Latest Threads

Top