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:
Example
>>> #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 10
- Python Class and Instance Attributes with Examples
- Python Data Persistence – ORM – Relationships
- Python Data Persistence – class Keyword
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 myclass.py script, let us now define age and name properties to interface with ___myage and ___myname private instance attributes.
Example
#myclass.py 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.
Example
>>> 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 >>> obj1.name name getter method 'Ashok' >>> 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.