1. Definition
Descriptor is how python’s property type implemented.
2. Creating descriptors using class methods
A descriptor simply implements _get_, _set_, _delete_, and then is added to another class in it’s definition.
- _get_(self, instance, owner):
access the attribute. It return value of attribute or raise the AttributeError exception if a requested attribute is not present. - _set_(self, instance ,value):
is called in an attribute assignment opeartion. Returns nothing - _delete_(self, instance):
controls a delete operation. Return nothing. - instance: 属性所属实例
e.g. <_main_.Person object at 0x104d2af70> - owner: 属性所属类
e.g. <class ‘_main_.Person’>
class Descriptor1(object):
def __init__(self):
self.name = ''
def __get__(self, instance, owner):
print("Getting: {}".format(self.name))
return self.name
def __set__(self, instance, name):
print("Setting: {}".format(name))
self.name = name
def __delete__(self, instance):
print("Deleting: {}".format(self.name))
del self.name
class Descriptor2(object):
def __set__(self, instance, age):
print("Setting Age: {}".format(age))
self.age = age;
def __get__(self, instance, owner):
'''
instance:
descriptor所属的实例
owner:
descriptor所属的类
'''
print(instance, owner)
print("Getting Age: {}".format(self.age))
return self.age
def __delete__(self, instance):
print("Deleting Age: {}".format(self.age))
del self.age
class Person(object):
# name = Descriptor1()
# age = Descriptor1()
name = Descriptor2()
age = Descriptor2()
if __name__ == "__main__":
obj1 = Person()
obj1.name = "hyl"
obj1.name
del obj1.name
Output:
3. Creating descriptors using property type
class property(fget, fset, fdel, doc) -> 新式类属性
fget: 获取属性的函数
fset: 设置属性的函数
fdel: 删除属性的函数
doc: 描述属性的信息
class Person(object):
def __init__(self):
self._name = ''
def fget(self):
print("Getting: {}".format(self._name))
return self._name
def fset(self, value):
self._name = value
print("Setting: {}".format(self.name))
def fdel(self):
print("Deleting: {}".format(self.name))
qdel self._name
property(fget, fset, fdel, "property type")
Output:
Clearly, the result is the same. Note here that fget, fset and fdel methods are optional, but if one is not specified, an exception of AttributeError is raised when the respective operation is attempted. For example, a name property is declared with None as fset, and then developor tries to assigin value to name attribute. An exception AttributeError is raised.
This can be used to define read-only attributes in the system.
name = property(fset, None, fdel, "I'm the property")
user.name = 'john smith'
output:
4. Creating descriptors using property decorators
property 的 getter,setter 和 deleter 方法同样可以用作装饰器
class Person(object):
def __init__(self):
self._name = ''
@property
def name(self):
print("Getting: {}".format(self._name))
return self._name
@name.setter(self):
def name(self, value):
self._name = value
print("Setting: {}".format(self._name))
@name.deleter(self):
def name(self):
print("Deleting: {}".format(self._name))
del self._name
Output: