Read-only attributes using properties?
Bengt Richter
bokr at oz.net
Thu Nov 21 12:44:41 EST 2002
On 21 Nov 2002 05:27:55 -0800, wolfoxbr at hotmail.com (Roberto Amorim) wrote:
>I was thinking about trying to use the new properties on Python 2.2 to
>implement read-only attributes. So I tried the following:
>
>class MyException(Exception):
> pass
>
>class TProp(object):
> def __init__(self):
> self.a = 0
> def get_a(self):
> return self.a
> def set_a(self, v):
> raise MyException
> a = property(get_a, set_a, None, "Test a")
>
>t = TProp()
>print t.a
>t.a = 5
>
>I was expecting that the script would fail with an exception on the
>"t.a = 5" command. However, I was surprised to see the code fail on
>the attribution inside __init__ - that is, there is no "inner class
>scope", or direct access within the class itself, and no clear way to
>initialize the property. If the property is an alias to the real
>internal variable (call it size, for instance), it works, but then if
>I try to add a __slots__ list excluding the internal var and only
>adding the external reference (__slots__=("a")) it stops working
>again.
>
>Is there any other way to do that?
>
If by "that" you mean implementing a read-only property, just leave out the "write":
>>> class TProp(object):
... def __init__(self):
... self._a = 0
... def get_a(self):
... return self._a
... a = property(get_a, None, None, "Test a")
...
(I.e., just omit set_a and specify None in the corresponding property arg)
>>> t = TProp()
>>> print t.a
0
>>> t.a = 5
Traceback (most recent call last):
File "<stdin>", line 1, in ?
AttributeError: can't set attribute
However, Python doesn't shut you out totally:
>>> t._a = 5
>>> print t.a
5
You need a separate name for the actual data, because the property action triggers by way
of finding the property name as a class attribute when looking it up via an instance.
BTW, looking it up directly gets you the property object itself without triggering its action:
>>> TProp.a
<property object at 0x007AA470>
To illustrate further(I think this is ok, but I'm not sure if it's frowned upon):
>>> TProp.b = property(lambda self: self._b, None, None, None)
>>> t._b = 'aha'
>>> t.b
'aha'
>>> t.b = 'oho'
Traceback (most recent call last):
File "<stdin>", line 1, in ?
AttributeError: can't set attribute
Regards,
Bengt Richter
More information about the Python-list
mailing list