Python描述符__get__,__set__,__del__
1、什么是描述符
1、从字面意思:假设一个人,这个人有很多的属性(名字、年龄、升高、体重等),而描述符就是对这些属性的限制,及描述符就是对对象属性的一种限制,或者说在对象赋予这个属性之前的一种操作(扩展)
2、描述符协议
注意:python3以后,自定义的类都是新式类,python2中class MyClass(object)才是新式类
一个新式类中,至少实现了__get__(),set(),delete()中的一个,这也被称为描述符协议:
get():调用一个属性时,触发
set():为一个属性赋值时,触发
delete():采用del删除属性时,触发
3、描述符的作用
描述符的作用是用来代理另外一个类的属性的(必须把描述符定义成这个类的类属性,不能定义到构造函数“init()”中)
4、描述符分的分类
1、数据描述符:至少实现了__get__()和__set__()
2、非数据描述符:没有实现__set__()
5、描述符定义要求
1、描述符及被代理的类都必须是新式类
2、描述符必须是代理类的类属性,不能在__init__方法中定义
3、要严格遵循该优先级,优先级由高到底
6、类属性、描述符、实例属性的优先级
优先级由高到底:
1.类属性
2.数据描述符
3.实例属性
4.非数据描述符
5.找不到的属性触发__getattr__()
五、描述符的应用
PeoPel表示人类,实例化一个人的对象,这个对象有name,age,height,weight
# 数据描述符
class A:
def __init__(self, key, DesType):
self.key = key # 属性名
self.DesType = DesType # 属性值的类型
def __set__(self, instance, value):
# instance:表示被代理类,实例化的对象
# value:被赋予的属性值
print(value, 'set')
if not isinstance(value, self.DesType):
raise TypeError("%s is not %s" % (value, self.DesType))
instance.__dict__[self.key] = value
def __get__(self, instance, owner):
# instance:表示被代理类,实例化的对象
# owner:表示被代理类
print(instance.__dict__[self.key], 'get')
return instance.__dict__[self.key]
class B:
name = A('name', str) # 表示B类name属性被代理了
def __init__(self):
self.name = "张三" # 就是给name赋值,触发代理类__set__方法
if __name__ == "__main__":
obj = B()
print(obj.name, 'B实例的name属性') # obj.name获取name属性是触发__get__方法
# 输出结果:
张三 set
张三 get
张三 B实例的name属性
# 非数据描述符
class A:
def __init__(self, key, DesType):
self.key = key
self.DesType = DesType
def __get__(self, instance, owner):
print(instance.__dict__[self.key], 'get')
return instance.__dict__[self.key]
class B:
name = A('name', str) # 表示B类name属性被代理了
def __init__(self):
self.name = "张三" # 就是给name赋值,触发代理类__set__方法
if __name__ == "__main__":
obj = B()
print(obj.name, 'B实例的name属性') # obj.name获取name属性是触发__get__方法
# 输出结果:
张三 B实例的name属性 # 非数据描述符没有触发__get__(),实例属性优先
# 类属性
class A:
def __init__(self, key, DesType):
self.key = key
self.DesType = DesType
def __set__(self, instance, value):
print(value, 'set')
if not isinstance(value, self.DesType):
raise TypeError("%s is not %s" % (value, self.DesType))
instance.__dict__[self.key] = value
def __get__(self, instance, owner):
print(instance.__dict__[self.key], 'get')
return instance.__dict__[self.key]
class B:
name = A('name', str) # 表示B类name属性被代理了
def __init__(self):
self.name = "张三" # 就是给name赋值,触发代理类__set__方法
if __name__ == "__main__":
obj = B()
B.name = '李四' # name重新赋值属于类属性,而不是描述符了
obj.name = "sss" # 实例重新赋值,name没有被描述符代理,不会触发__set__方法
print(obj.name, 'B实例的name属性') # obj.name获取name属性是触发__get__方法
结果:
张三 set
sss B实例的name属性