470,810 Members | 861 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 470,810 developers. It's quick & easy.

best practices for making read-only attributes of an object

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

Mar 15 '06 #1
2 1136
Tim Chase wrote:
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
--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'o****@xiludom.gro'.split('@')])"
Mar 15 '06 #2
bruno at modulix wrote:
Tim Chase wrote:

class Foo:


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/
Mar 15 '06 #3

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

136 posts views Thread by Matt Kruse | last post: by
13 posts views Thread by john doe | last post: by
10 posts views Thread by jojobar | last post: by
3 posts views Thread by newtophp2000 | last post: by
26 posts views Thread by puzzlecracker | last post: by
4 posts views Thread by Ned Balzer | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.