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._name
More 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