Python Descriptors
Python descriptors are a way to create managed attributes. Among their many advantages, managed attributes are used to protect an attribute from changes or to automatically update the values of a dependent attribute. The methods needed to create a descriptor are __get__, __set__ and __delete__. If you define any of these methods, then you have created a descriptor.
Descriptor Protocol
The descriptor protocol is simply a set of methods a class must implement to qualify as a descriptor. There are three of them:
__get__(self, instance, owner)
__set__(self, instance, value)
__delete__(self, instance)__get__ accesses a value stored in the object and returns it.
__set__ sets a value stored in the object and returns nothing.
__delete__ deletes a value stored in the object and returns nothing.
It is important to note that descriptors are assigned to a class, not an instance. Modifying the class overwrites or deletes the descriptor itself, rather than triggering its code.
When Descriptors Are Needed
Consider an email attribute. Verification of the correct email
                format is necessary before assigning a value to that attribute. This
                descriptor allows email to be processed through a regular expression and
                its format validated before assigning it to an attribute. 
In many other cases, Python protocol descriptors control access to attributes, such as protection of the name attribute.
Creating Properties
You can create a descriptor a number of ways:
- Create a class and override any of the descriptor methods: __set__,__ get__, and__delete__. This method is used when the same descriptor is needed across many different classes and attributes, for example, for type validation.
- Use a property type which is a simpler and more flexible way to create a descriptor.
- Use the powe r of property decorators which are a combination of property type method and Python decorators.
class Person(object):
 
    def __init__(self):
        self._name = ''
 
    @property
    def name(self):
        print "Getting: %s" % self._name
        return self._name
 
    @name.setter
    def name(self, value):
        print "Setting: %s" % value
        self._name = value.title()
 
    @name.deleter
    def name(self):
        print ">Deleting: %s" % self._name
        del self._nameMore about @property decorator: https://stackoverflow.com/questions/17330160/how-does-the-property-decorator-work
Reference:
https://www.ibm.com/developerworks/library/os-pythondescriptors/index.html