Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the easiest, most concise way to make selected attributes in an instance be readonly?

In Python, I want to make selected instance attributes of a class be readonly to code outside of the class. I want there to be no way outside code can alter the attribute, except indirectly by invoking methods on the instance. I want the syntax to be concise. What is the best way? (I give my current best answer below...)

like image 426
Kevin Little Avatar asked Sep 24 '08 02:09

Kevin Little


People also ask

How do I make an attribute read-only?

If you need to make a read-only attribute in Python, you can turn your attribute into a property that delegates to an attribute with almost the same name, but with an underscore prefixed before the its name to note that it's private convention.

What is a read-only property in Python?

To define a readonly property, you need to create a property with only the getter. However, it is not truly read-only because you can always access the underlying attribute and change it. The read-only properties are useful in some cases such as for computed properties.

How do you make class attributes private in Python?

But there is a method in Python to define Private: Add “__” (double underscore ) in front of the variable and function name can hide them when accessing them from out of class. Python doesn't have real private methods, so one underline in the beginning of a method or attribute means you shouldn't access this method.

What is __ slots __ in Python?

slots provide a special mechanism to reduce the size of objects.It is a concept of memory optimisation on objects. As every object in Python contains a dynamic dictionary that allows adding attributes. For every instance object, we will have an instance of a dictionary that consumes more space and wastes a lot of RAM.


2 Answers

You should use the @property decorator.

>>> class a(object):
...     def __init__(self, x):
...             self.x = x
...     @property
...     def xval(self):
...             return self.x
... 
>>> b = a(5)
>>> b.xval
5
>>> b.xval = 6
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: can't set attribute
like image 91
William Keller Avatar answered Oct 20 '22 16:10

William Keller


class C(object):

    def __init__(self):

        self.fullaccess = 0
        self.__readonly = 22 # almost invisible to outside code...

    # define a publicly visible, read-only version of '__readonly':
    readonly = property(lambda self: self.__readonly)

    def inc_readonly( self ):
        self.__readonly += 1

c=C()

# prove regular attribute is RW...
print "c.fullaccess = %s" % c.fullaccess
c.fullaccess = 1234
print "c.fullaccess = %s" % c.fullaccess

# prove 'readonly' is a read-only attribute
print "c.readonly = %s" % c.readonly
try:
    c.readonly = 3
except AttributeError:
    print "Can't change c.readonly"
print "c.readonly = %s" % c.readonly

# change 'readonly' indirectly...
c.inc_readonly()
print "c.readonly = %s" % c.readonly

This outputs:

$ python ./p.py
c.fullaccess = 0
c.fullaccess = 1234
c.readonly = 22
Can't change c.readonly
c.readonly = 22
c.readonly = 23

My fingers itch to be able to say

    @readonly
    self.readonly = 22

i.e., use a decorator on an attribute. It would be so clean...

like image 34
Kevin Little Avatar answered Oct 20 '22 17:10

Kevin Little