Python Data Persistence – property () Function

Python Data Persistence – property () Function

Well, let me now make a volte-face here. It’s not that Python doesn’t have private/protected access restrictions. It does have. If an instance variable is prefixed with double underscore character ‘___’, it behaves like a private variable. Let us see how:


>>> #private variable in class
. . .
>>> class tester:
. . .             def___init___(self) :
. . .                       self.__var=10
. . .

Try .declaring an object of above class and access its__var attribute.

>>> t=tester( )
>>> t.__var
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'tester' object has no attribute '___var'

The AttributeError indicates that the variable prefixed is inaccessible. However, it can still be accessed from outside the class. A double underscore prefixed attribute is internally renamed as obj ._class var. This is called name mangling mechanism.

>>> t._tester var

Hence, the so-called private variable in Python is not really private. However, a property object acts as an interface to the getter and setter methods of a private attribute of the Python class.
Python’s built-in property() function uses getter, setter, and delete functions as arguments and returns a property object. You can retrieve as well as assign to the property as if you do with any variable. When some value is assigned to a property object, its setter method is called. Similarly, when a property object is accessed, its getter method is called.

propobj=property(fget, fset, fdel, doc)

In the above function signature, fget is the getter method in the class, fset is the setter method and, fdel is the delete method. The doc parameter sets the docstring of the property object.
In our ongoing script, let us now define age and name properties to interface with ___myage and ___myname private instance attributes.

class MyClass:
        __slots___= ['__myname' ,'___myage ' ]
        def__init__(self, name=None, age=None):
               self. myname =name
               self. myage=age
        def getname(self):
            print ('name getter method')
            return self. ___myname
       def setname(self, name):
           print ('name setter method')
           self. ___myname=name
      def getage(self):
           print ('age getter method')
           return self.____myage
      def setage(self, age):
           print ('age setter method') 
       self. ____myage=age
name=property(getname, setname, "Name") age=property(getage, setage, "Age") def about(self) :
print ('My name is { } and I am { } years old'.format(self.___myname,self. __myage))

We’ll now import this class and use the properties. Any attempt to retrieve or change the value of property calls its corresponding getter or setter and changes the internal private variable. Note that the getter and setter methods have a print () message inserted to confirm this behavior. The about () method will also show changes in private variables due to manipulations of property objects.


>>> from myclass import MyClass
>>> obj1=MyClass(1Ashok' , 21)
>>> obj1.about() #initial values of object's attributes
My name is Ashok and I am 21 years old
>>> #change age property
>>> obj1.age=30
age setter method
>>> #access name property
name getter method
>>> obj1.about( ) #object's attributes after property changes
My name is Ashok and I am 30 years old

So, finally, we get the Python class to work almost similar to how the OOP methodology defines. There is a more elegant way to define property objects – by using @property decorator.