readonly class attribute ?

bruno modulix onurb at xiludom.gro
Tue Mar 15 14:21:19 EST 2005


Hi

How can I make a *class* attribute read-only ?

The answer must be pretty obvious but I just can't find it (it's late 
and I've spent all day on metaclasses, descriptors and the like, which, 
as fun as it is, may have side-effects on intellectual abilities...)

*The context:*

# library code
class AbstractBaseClass(object):
    # snip some stuff here,
    # a part of it depending on the derived classes
    # defining class attribute class_private_attrib

# client code
class SubClass(AbstractBaseClass):
    class_private_attrib = "my private attrib"
    # snip


*What I'm looking for: (if possible)*

 >>SubClass.class_private_attrib
"my private attrib"
 >>SubClass.class_private_attrib = "toto"
AttributeError : SubClass.class_private_attrib is read only
 >>s = SubClass()
 >>s.class_private_attribute = "toto"
AttributeError : SubClass.class_private_attrib is read only

*What I've tried: (simplified as possible)*

class ReadOnlyDescriptor(object):
     def __init__(self, name, initval=None):
         self._val = initval
         self._name = name

     def __get__(self, obj, objtype):
         print 'Retrieving', self._name
         return self._val

     def __set__(self, obj, val):
         raise AttributeError, \
         "%s.%s is ReadOnly"  % (obj.__class.__.__name__, self._name)

class SubClass(object):
    class_private_attrib = ReadOnlyDescriptor("class_private_attrib",
                                               "my private attrib")
    # snip

*What i get:*
 >>SubClass.class_private_attrib
Retrieving class_private_attrib
"my private attrib"
 >>SubClass.class_private_attrib = "toto"
 >>SubClass.class_private_attrib
"toto"
 >>SubClass.__dict__['class_private_attrib']
"toto"
 >> s = SubClass()
 >> s.class_private_attrib
"toto" # of course :(

*What I understand:*
Ok, I've re-read the manual, noticed that data descriptors __set__() 
method was only called when an instance attribute is set (which is 
obvious from the prototypes of the methods). My solution is plain wrong 
and I should have guess without ever trying. duh :(


Now please have mercy, you Noble Pythoneers : what's the trick to 
prevent client code to accidentally mess with the class's dict ? (most 
client code - apart from subclass definitions - shouldn't even bother 
about the existence of this attribute, it's there for the library 
internal usage)

NB : in the real code I'm also messing with the AbstractBaseClass's 
meta_class for other stuff (so it's not a problem if the solution 
involves metaclasses), but I've tested with the simplified example 
above, which exhibits the same problem.

TIA
-- 
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for 
p in 'onurb at xiludom.gro'.split('@')])"



More information about the Python-list mailing list