howto prevent class variable assignment
Peter Otten
__peter__ at web.de
Sun Feb 1 11:53:34 EST 2004
Uwe Mayer wrote:
> when an instance variable of a class is not found, python tries to fall
> back to the class variable.
> I want to use that feature to provide default settings for a class which
> can be overwritten by assignments to variables with the same name.
>
> This quickly becomes difficult to handle when you get confused wether your
> assignment was made to a class variable or an instance variable. I
> therefore want to prevent write access to class variables. How do I do
The sane way would be to copy mutable defaults in __init__().
> that?
>
> Here some example code:
>
>>>> class A(object):
> ... cInt = 5
> ... cList = [1,2,3]
> ... def __init__(self):
> ... self.cInt = 6
> ...
>>>> a = A()
>>>> a.cInt
> 6
>>>> a.__class__.cInt
> 5
>
>>>> a.cList[2] = 5 #<-- prevent this
I fear this is *hard* as you are just changing an instance of a mutable
class. Maybe you could write a general readonly wrapper?
>>>> a.cList
> [1, 2, 5]
>
>>>> a.cInt = 42 #<-- allow this
>>>> a.cInt
> 42
>>>> a.__class__.cInt
> 5
>
>>>>A.cInt = 10 #<-- prevent this
>
> I tried to overwrite __setattr__(self, name, value) method, but this is
> only called if I call it on an instance, i.e.
>
>>>> a.cInt = 5
>
> but not when I call it on the class:
>
>>>> A.cInt = 10
>
>
> Can anyone give me some pointers or suggentions how to handle this?
A is an instance of its metaclass, so you have to devise a way to prevent
write access for metaclass instances.
Below is an example that uses the "sealed" attribute to prevent further
write access when you are done defining the class:
>>> class Type(type):
... def __setattr__(self, name, value):
... if hasattr(self, "sealed"):
... raise Exception("Attempt to set class att
ribute")
... type.__setattr__(self, name, value)
...
>>> class Test:
... __metaclass__ = Type
... x = 123
... y = 456
...
>>> Test.x = 111
>>> Test.sealed = True # class attributes can no longer be rebound (más o
menos)
>>> Test.x = 222
Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "<stdin>", line 4, in __setattr__
Exception: Attempt to set class attribute
>>> t = Test()
>>> t.x = 789 # instance attributes behave just normal
>>>
Again, this will not prevent changing a mutable instance, e. g. setting a
list item. Your time is probably better spend on writing a good test suite
for your app.
Peter
More information about the Python-list
mailing list